Construct 3 : Functions improvement & refactor.

  • Hi Ashley and the rest in the Construct Team.

    I would like to talk about the Functions built-in. There seems to be 2 issues I've found. I understand how much thought you've might given the new Functions, but I think you might have missed a few important points.

    1. Redundancy
    2. Limitation

    I've made a few events to showcase the issues I've encountered. There are lots more actually but I think this is enough to give a point and to show the solution's effectiveness.

    Redundancy

    Mapping

    The current state of the Functions built-in has a few unnecessary parts, specifically the Map Function to string.

    By design, a Construct 3 function is already a string, for simplicity sake, can we instead of Map function to string to use the function name instead as a string reference.

    It doesn't feel like it's worth all the trouble. Considering less events are better in both performance and readability.

    If you really think mapping features are necessary, then I think this should be left as optional, like a tag action.

    Redundancies are something we can still endure though but I think it can be on its best when remaining simple but effective.

    Limitations

    Unlike redundancies, limitations are the project stopper on the user end. They make it nearly impossible or at least hard to manage development. I'll show a quick show why,

    Parameters & Expression Function Call

    Parameters ::

    It's of an upmost importance to be able to control the parameters, for example making a dynamic function inside a current function where the input parameters of the current function determines which function will run and what parameters are passed.

    Just like the screenshot above, the ConversionMode controls the function to be called for and what parameters are passed, dependent on the process output data.

    It might come of question:

    Why not make direct call function and make the comparison on a base event?

    It's because of its inefficiency in readability, organization and event count-performance. For example, I've done a function of a Character Creation Class, which has its own sub-class functions (Not in the same event). Calling those sub-class functions on the parent event instead can lead to very confusing events, almost impossible to call organized.

    It can be said similar to developing a regular app using JS without passing dynamic arguments or functions having the same parameters when passed.

    We are already limited to Global Functions, I feel like we don't want to add any more limitations like this.

    Parameter Count & Param(i) ::

    I have to give it to the Construct Team. The default function is a great feature. A fallback for a function is very handy, and it also gives an opportunity to showcase a limitation.

    We know the it basically passes all the parameters of a misfired function to the default function.

    Although, the passed parameters are lost.

    The problem here is that, similar to the regular built-in function, we can't manage the parameters, like get its Count and Param(i), where it's crucial for this to work.

    JavaScript has this feature, Construct 2 also has this feature. I believe it's really crucial to get these features back.

    Other info

    I understand the amount of thought and work you guys have made, it might work in the theory planning, but I can assure that it's really hard to do in real development.

    I asked other regular users of Construct 3 on how they managed to get around these limitations. Interestingly, I got these answers:

    1. They use scripting. And they even suggested me to do that.
    2. They use the old Construct 3 Function by importing a Construct 2 .capx with a Function plugin.

    The first idea makes sense, but with my workflow, I only want to use scripting when it can't be done with Construct 3's core plugin. And that makes sense, cause Construct 3 promotes being mainly visual-editor based.

    The 2nd one, I've done that for my projects. But, after the variadic-parameters issue, it broke lots of projects, including mine. If a time comes where the old Construct 3 Function becomes depreciated, it would be another rewrite and heavier this time. Which I'm not planning to go with again.

    As much as possible, I'd like it resolved now, while it's early.

    Solution

    Redundancies

    The redundancy issue compromises a bit of organization of events and increases event count, but nothing that isn't manageable. But it can become better.

    I have a suggestive solution,

    Instead of having the Call mapped function, how about just making it into a Call action. Instead of having the Map default function, how about making it Set default function. With this, we don't need to Map function to string since a function is already a referenced by a constant string. Especially, we wouldn't need maps at all.

    The function name is already a great candidate for a function reference string. But if you really need to, a Tag function to string action can also be an option.

    Limitations

    Parameters ::

    I'm not sure why the Functions (built-in) had an ACE change, but I'm guessing it has something to do with Variadic Parameters. But if that's the case, an easy solution is add new actions to the actions list, that would be the following:

    A parameter stack, would be a great replacement. I've tried it and it's an easier replacement to use.

    Parameter Count & Param(i) also Compare ::

    Having the expressions ParamCount & Param(i) and the condition Compare Parameter as an additional feature would really be useful on dynamic cases.

    Basically, at this point, I'm asking for integration of the old Function to the new built-in Functions.

    Hoping for your kind consideration.

    Thank you for your time.

  • For those who use the old Functions and scripting to workaround the limitations of the built-in Functions. Please help out to support the request for the improvement of the new built-in Functions. Thank you!

  • Great analysis, chadorireborn!

    Yeah, I miss the flexibility of the old functions, where you could pass any number of parameters and let the function to decide what to do with them..

    .

    I want to add one small UI issue - when you have lots of functions in the project, "Set return value" action becomes buried in them:

  • Thanks for sharing that info. 🙂

  • I want to add one small UI issue - when you have lots of functions in the project, "Set return value" action becomes buried in them:

    By giving your functions their own "Category" it won't clutter the "Functions" category. Not perfect, but it becomes easier to spot the lone "Set return value" that way.

  • If we made these changes it would basically regress the built-in functions to the old design, which people asked us to change for good reasons.

    For example people got annoyed that renaming a function was difficult because you had to update a bunch of strings everywhere. The new functions system fixes this, and function mapping is specifically designed to de-couple the string from the function, so that you can always rename functions without having to update a bunch of strings too. You call it redundancy, but actually it's to improve refactoring, which was a major user request. If we go back to referring functions by name, we regress back to renaming functions sometimes breaking your project, which re-creates the whole problem we were trying to fix in the first place.

    As for accessing parameter counts and parameters by index, adding this would also regress the usability of functions in various ways. For example with built-in functions you can refer to parameters by their name - another top request. If we add indexed parameters we regress back to unnamed parameters, which is what we were trying to fix in the first place. It could also cause refactoring problems as well - for example with built-in functions you can just drag and drop parameters and the entire project updates automatically (something that was also previously involved a lot of manual work to update); if you can refer to parameters by their index, this re-creates the original problem that reordering parameters can break your project unless you do a bunch of manual work.

    If there are still shortcomings I'd really want to fix them without recreating the original problems! For example with variable numbers of parameters, some languages do not allow this at all. Instead you can do things like pass arrays. In Construct you could already use an Array object to set a variable amount of data in which then gets used by the function. So I think there are already ways to handle this, you just need a different set of techniques. If that still doesn't cut it for whatever reason, then I would want to think about a better design that isn't going to bring up the same problems and cause the same feature requests of "please fix this problem" that we already dealt with.

  • Ashley, I guess we can't change what's done. This on the other-hand seems feasible:

    Add Parameters & Call Function (blank parameters)

    We at least could use a way to pass parameters ourselves. Cause, dynamic function-parameters are still very important. I couldn't port a project without this, it's a common function utility after all.

  • Isn't that the same thing as passing parameters by index, with the same problems?

  • Because, there's currently no way to call a dynamic function without passing the same parameters. We could overwrite, but what about functions with more parameters?

    Ashley

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • Though honestly Ashley, I just want you to think about it for a second, at our standpoint. (I'm saying this respectfully) Do you really think this new built-in Functions easier to use than just use JS at this point? Because, if you ask me, it went from user-friendly Functions to puzzle-game Functions.

    Construct 3 was supposed to be user-friendly.

  • That example doesn't seem to make sense. Why would you pass RGBA parameters as CMYK? That's passing them as a different format.

  • Ashley

    That example doesn't seem to make sense. Why would you pass RGBA parameters as CMYK? That's passing them as a different format.

    I just wanted to point out, how parameters can change when they receive it. The first function receives an RGBA, the second one receives a CMYK passed on to it, also HEX where it added more parameters.

    I just wanted to point out how the Call mapped function is limited for passing parameters.

  • Ashley, is it possible to implement overloaded functions (as in Java for example)? Where you can have 2 or more functions with the same name, but different sets of parameters?

  • I like the new functions much better than the old one--however, as others pointed out--I keep losing the set return parameter in my list of functions. I now put everything in a catagory that starts with a letter after f so the "set return parameter" is at the top of the list.

    There is another problem with functions--suppose i have a local static variable in my group name and functons in the group that reference it. If I disable the group the function still gets found but the variable the function needs does not.

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)