Overboy's Forum Posts

  • You do not have permission to view this post

  • I forgot to mention it but this is happening to me since at least r332 (not just since last stable r336 release)

  • It happened to me several times too. The editor was completely frozen and I had to close c3 without saving.

    I'm using project folder.

  • I posted a suggestion on the dedicated platform for the Listener Blocks suggestion (what i previously called "Special Triggers") which would allow us to turn any Function or Custom Action into a Better Signal (passing parameters, featuring the same performance and UX benefits as Functions, and an execution order feature).

    construct23.ideas.aha.io/ideas/C23-I-165

  • Thanks for your input TackerTaker.

    The Listener Block feature must be seen as if they were brand new Functions/Custom Actions, but automatically called at the same time and passing the same parameters as their "parent" Function/Custom Action.

    It shouldn't be seen as the same Function/Custom Actions defined in multiple places, as your mockup show. I agree this wouldn't work and it would be confusing.

    Instead it's like if they were 2 different functions under the hood, called with a single call and the same parameters. Similarly to how works a Delegate pattern for example. (I know this isn't actually like Delegate pattern)

    In fact the implementation under the hood would be exactly the same as built-in Function, but the user wouldn't need to set-up an extra Function, to set-up exactly the same parameters, and to call that extra Function at the same time in everyplace the original function and making sure that function is called with the exact same parameter.

    Also the execution order feature solve a lot of complex race conditions issues that can happen right now for any vanilla C3 Trigger Condition (including the new "On Signal Trigger") and are sometimes painful to workaround.

    Of course the point of this isn't to call the same logic twice as your "Enemy action rotate" Mockup shows.

    The same way it wouldn't make sense to execute the same logic twice while using any other C3 Condition. You would have the same issue if you clone any event block in C3 with the exact same conditions and actions. The mistake someone can make to execute the same action twice instead of 1 isn't specific to "Listener Blocks", it can be made anywhere in a project inadvertently.

    You would be easily able to find all "Listener Blocks" and the Function Definition thanks to the "Right Click Context Menu> Go to Function Definition" and "Right Click Context Menu> Find all function references", in case you need to Debug something. While it would be really more painful to do that exact thing if you would need to set up 12 different functions with exactly the same parameters called exactly at the same time as each of them would have a different name. You would need to look for the 12 different names using the Event Search feature, on top of all that extra painful set-up work.

    I don't think that feature should be done with Signal but as the same implementation as built-in Function (as Custom Actions are), so we would still have all the UX benefits, the parameters feature, and the amazing performance of Ashley's Function implementation that in fact, under the hood are executed only in one place.

    I'm using Chadori's Self Function extensively for a year for all my projects. Like 70% of all my "functions" were in fact Chaodri's Self Function that whole time, using polymorphism and multiple trigger blocks feature before Scirra even announced they were working on Custom Actions. So i can get why the need of Multiple Triggers doesn't seem obvious as Custom Actions were just released in beta, they're still bugged and nobody build several months-long project on top of them, push them to their limits.

    But i can guarantee I would never ever switch back to built-in Function/Custom Actions until this multiple Trigger Block feature is implemented. I just couldn't make my project at all without this.

    Still i'm happy for the other users that those feature were released, but they're still inferior of what i'm doing with Self Functions right now so I wouldn't switch to the new "On Trigger signal" and "Custom Actions" because of this.

    (If someone at Scirra wants to understand why this is so much important I can show them how i'm doing my projects by mail or Private Message.)

    Interesting, didn't know about Trusted Web Activities. However this is different from the embedding method I described. First because it works only for Google Play but also because as you pointed out it wouldn't work for ads or IAP.

    Ashley, I sent to your ash@ adress a link to download the .apk of some of those games i'm thinking about. So you can check how the embedding works and how they manage to trigger actual Android ads if you're interested. Thanks to this method, those apps are only 15-20 Mb to download. Don't know if it's realistic but maybe it's worth investigating.

    EDIT : To answer that last post about locking the thread, I don't think this thread was about multiple topics with no connection. It was a particular performance issue case that turned into a discussion around the Mobile performance issue as a whole, which seems to be a recurring issue for C3 Mobile devs.

    Could the guys downvoting the Mobile Export with Web Export embedding idea explain why they think it wouldn't work ? I'm probably missing something.

    Because it looks like it would solve several issues including that performance thing everybody is talking about ?

    I'm actually also thinking Mobile desserves more love and that suggestion is helping at least with the performance issue of Mobile Export.

    As some people pointed out the C3 engine is rock solid for Webs but Android/IOS export are bad, so if Mobile Exports are in fact Web Exports it would literally solve this issue in a easy way on top of many other benefits. (no need to update the game on both stores each time + very little download size = low barrier for a user to download the app while browsing the stores)

    Regarding the Mobile Export and Performance issues, i'm thinking about something for a few months.

    What about a new way to export to Mobile Devices that would consists in a default "empty" IOS/Android build where we would just embed a web export we host somewhere else?

    The "empty" IOS/Android would just launch "Android ads"/"IOS ads" when the embeded web export calls it. It would listen for stuff that triggers in the actual Web game.

    The only thing we would need to do is :

    1. Generate an "empty" IOS/Android app
    2. Export the actual game to web
    3. Host the web export somewhere
    4. Change an URL value in the "empty IOS/Android app" to put the right link of the game, so the Web export is embed in the Android app
    5. Publish on IOS/Android

    There would be many benefits :

    • better perfomance (web export are way better than mobile exports apparently)
    • very low app download size (the game is hosted in web so it's not part of the downloaded app)
    • 1 single export to many platforms
    • no need to update on IOS/Android/Web each time, we just need to update the game where it's hosted in the web

    I've seen several apps doing this so their download size from the store is only something like 15-20 mb, and they're really performant.

  • EDIT : Just released an addon pack implementing everything i've been advocating for !

    Grab it here if you want to create Object-based signals, passing instances and supporting multiples parameters + custom expressions

    overboy.itch.io/construct-3-object-signals-custom-expressions

    Hi Ashley, thanks a lot for the amazing features pushed recently and for integrating the suggestion regarding Polymorphism for Custom Actions. After thinking about it longer, I must admit you were right about the implementation you chose for Custom Actions (based on the same implementation as Functions).

    I have a few more feedbacks/suggestions to give as Custom Actions are still WIP and now I know better about your plans with them.

    1. New “Listener Blocks" : the user could create as many extra Trigger blocks as they want for each Function and Custom Action with a boolean "Emit Signal" set to true and it would feature an execution order feature.

    => Those extra “Listener Blocks" would in fact be similar to Functions/Custom Actions but they would be called at the same time and with the same parameters as their related Function/Custom Action. This means a Function/Custom action would allow us to execute logic in multiple place in the eventsheet and to pass the parameters/Object UIDs in those places : it would work kinda like a "Better Signal" feature but allowing us to do even more (execution order) and with the top performance and ergonomy of Functions/Custom Actions.

    2. Calling a Function/Custom Action by its name

    3. Custom Expressions.

    I. LISTENER BLOCKS

    construct23.ideas.aha.io/ideas/C23-I-165

    = Extra Listener Trigger Blocks for Functions and Custom Actions

    = “On Custom Action called” / “On Function called“

    A. Listener Blocks :

    • Add a new "Emit Signal" boolean for Function/Custom Actions. (set to false by default)
    • If it's set to true, the user can add as many extra “Listener Blocks” as they want related to that specific Function or Custom Actions.

    Listener Blocks are a new kind of Event Block (as Custom Actions or Functions, different from regular C3’s Triggers block). There are corresponding to an existing Function (or Custom Action) and they allow to use the parameters of this corresponding Function.

    Exception : The user can't create Listener Blocks for return type Function such as String/Number (they also can't create Listener Blocks potential future return type Custom Action = Custom Expression)

    They could be implemented in a similar way to Function/Custom Actions in term of performance (see details below)

    On the mockup above, you can see 2 “Listener Blocks” blocks corresponding to the “MyFunction1” built-in function. You can notice that :

    • The Symbol of Listener Blocks is a blue arrow, this is not a mistake : Listener Blocks are different from C3’s regular Trigger block (green arrow). This is because there are some kind of “pseudo functions” but with the same parameters as their linked Function block (so they would be as performant as built-in Function).
    • The Parameters are blue => it’s because as opposed to Function blocks, Listener Blocks blocks parameters can’t be edited, they’re just the same as their related Function block.
    • There is only 1 actual “MyFunction1” function block, but there can be un unlimited amount of “MyFunction1” Listener Blocks (here there are 2 of them)
    • The Right-Click context menu of a Listener Block is different from built-in Function block : it doesn’t allow to edit the function directly (but it allow to go to the function), it only allow to edit the Listener Block itself and it doesn’t allow to edit the parameters of the Function.

    It would work exactly the same for Custom Actions : we would be allowed to create corresponding Listener Blocks blocks for them.

    B. The Workflow to create Listener Blocks :

    There are multiple way the user could create those Listener Blocks, but here are the 2 best alternatives I can think of. (It could be only one of them or even both of them so everyone choose their favorite workflow)

    1) Creating Listener Blocks from Event sheets

    1/ It would be in the same context menu as where the user can create Functions and Custom Actions.

    2/ It would open a “Add Listener Blocks” pop-up with the object “Functions” selected by default. But the user can choose any actual Objects with Custom Actions instead thanks to a filtered object picker.

    3/ The user chooses the corresponding Function/Custom Action for the selected Object (if it’s not just the “Functions” Object).

    In the mockup, this is a string field with autocompletion because there could be issue with a dropdown list because of the huge amount of built-in Functions there could be. However it would be impossible to create a Listener Blocks for a non-existing Function/Custom Action. As you can see in all previous mockup the Listener Blocks doesn’t rely on an actual string for the Function they’re listening for. They're more like specialized Function as opposed to trigger events such as "On Tween [Tag] finished"

    (It could just be a dropdown list instead if browsing a potential big number of Function isn’t an issue)

    2) Creating Listener Blocks from Conditions

    The user would find a new Trigger Condition with blue arrows per Function/Custom Action in the conditions of Objects/Families with associated Custom Actions, or in the conditions of the “Functions” Object (which doesn’t have any condition yet in the engine).

    (I think this one is my favorite workflow among the 2 alternatives)

    Of course, if they're created from Conditions Pop-up, the creation of those Listener Blocks condition would be restricted the same way Regular Trigger are restricted but with an additional exception : they can't be in a subevent. (same restriction as any other function)

    C. Execution Order :

    On the previous mockups you can see “‘(Order : 0)” at the end of the Listener Blocks. This is corresponding to an optional but amazing-to-have feature that would be Execution Order for Listener Blocks.

    As you rightfully pointed in the last thread, the issue with Custom Triggers is annoying race conditions/issues with order of execution. This is also an issue with all existing Trigger Condition in construct such as “Object:On Created”, it’s pretty common to have to set-up a bunch of thing when an object is instanciated. Also on bigger project, for organisational purpose, it’s really important to be able to put the actions executed for Triggers in different places. But the execution order is a big and recurrent issue in C3.

    There are multiple way to implement this “Listener Blocks Execution Order”, and a big spectrum of capabilities for this feature. So here i’ll just present what I think is the most powerful and intuitive/easy to understand way to handle this for the user.

    The only specific parameter Listener Block would have would be a “Execution Order” number. (Default value is 0)

    • If Execution Order = 0, then it means the Listener Block is triggered exactly at the same time as the related Function. Which means it would be exactly the same as calling multiple built-in function at the same time with the same parameters but with a more pleasant workflow and without the need to create a bunch of functions while in fact i just want to call and define several of them at once. The user should not use order=0 if they absolutely need some events from other blocks to happen before.
    • If Execution Order > 0, then it means the Listener Block would wait for the related actual Function block to be finished, but also all other Listener Blocks with a smaller execution order.

    Example :

    In this example, I have a MyAction1 Custom Action with 4 related Listener Blocks with different execution order.

    1. When the Function is called, both the Custom Action and the Listener Blocks with order = 0 are executed.

    2. Once the Custom Action Block and the Listener Block with order=0 are finished, the 2 Listener Blocks with order = 1 are executed.

    3. Once the 2 Sepcial Triggers block with order=1 are finished, the last Listener Block with Order=3 is executed.

    Note 1 : this is not an issue that the last Listener Block order isn't order=2, it could also have been Order=4552, it would work exactly the same. No need for the execution order numbers to be consecutive. The only rules is the lowest order are executed first, and the highest order Listener Blocks wait for the lowest to be finished before they're executed.

    Note : Those Listener Blocks could be placed anywhere in the eventsheets, in any order. The Listener Block with Order = 3 could be placed above the rest for example, it would be the same result.

    D. Execution order + Polymorphism ? :

    The most simple way to handle both Custom Action Family polymorphism (Member overriding its Family Custom Action) and that execution order feature is to consider Listener Blocks from the Family custom action and the ObjectMember overriding custom action as related to 2 totally different Custom actions. Which means each of them have their corresponding Listener Blocks with their execution order, but the execution order of Family Listener Blocks doesn’t affect execution order of Object Member Trigger Events and vice versa.

    Maybe the only thing that could be interesting is the ability for the “super call” (Object Member calling back its Family custom action) to be set as asynchronous, so the user could add a “Wait for previous Actions” to make sure the whole Family Custom Action and all its Listener Blocks are executed before continuing.

    E. Asynchronous ? :

    The Execution Order feature would require the corresponding actual Function/CustomAction block to be set as “Asynchronous”. Only then the Execution Order of corresponding Listener Blocks can be edited, otherwise, their parameter is grayed out and is only equal to 0.

    That would be the only manual set-up the user would have to do : setting up the actual Function/Custom Action as asynchronous to be able to use this feature. So there would not be any overhead for Functions/Custom Actions by default.

    Listener Blocks, however, would not need any Asynchronous boolean to be set-up. Construct would automatically detect under the hood if there are same Listener Blocks with highest Execution Order Number, and handle the Event Listener automatically under the hood.

    II. NEW ACTIONS : Call Function / Call Custom Action by Name

    (this isn't related to "Listener Blocks", it's just an other feature related to Custom Actions/Functions)

    Add a new “Functions” action “Call Function by Name”

    Add a new Object action “Call Custom Action by Name” (for Objects with at least 1 custom Actions)

    Both actions could feature a string autocompletion with all possible Functions/Custom Actions Names.

    The Function/Action parameters are set in a second String field following this syntax "Param1, Param2, Param3"

    This would allow advanced users to create much more dynamic system without wasting all the UX benefits of C3 built-in Functions for the other users. For example, by playing Functions/Custom actions based on values stored in string variables at runtime.

    This feature would also work really well in combination with this other feature request I made on the platform

    Access hidden enums thanks to a new system Expression.

    construct23.ideas.aha.io/ideas/C23-I-69

    This way we could have autocompletion and auto-update of Function/Custom Action Name strings everywhere thanks to those system expressions.

    We could access the Functions/Custom Action names thanks to system expression such as

    EnumFunctions.MyFunction1 (so we could do "Function : Call function by name [EnumFunctions.MyFunction1]")

    EnumCustomActions.MyObject.MyCustomAction(so we could do "MyObject : Call custom action by name [EnumCustomActions.MyObject.MyCustomAction]")

    So if later I change the “MyFunction1” name to “Enemy_Death” in the built-in Function block, then the Function : Call Function by name would now be set to EnumFunctions.Enemy_Death automatically. No need to change a bunch of “MyFunction1” strings manually.

    This would allow us to create systems where we store functions names on variables easily at runtime and then just call a Function based on that variable !!

    => Endless new possibilities and capabilities for the C3 engine.

    III. CUSTOM EXPRESSIONS (= Custom Actions with return value)

    Here is a self-explanatory mockup :

    • Basically add a Return Type dropdown list parameter to custom Actions.
    • It would work the same as returned Function.
    • You can use them using an ObjectType.MyExpression(MyParams) expression.
    • You specify the value it returns thanks to a new Object action called "Set custom expression return value" you put in the special Custom Expression (=Custom Action) event block
    • The special event block would be named "MyObject expression MyExpression1 -> Number" like in the mockup.

    Custom Expressions, as return type Functions, would not support "Listener Blocks" (Suggestion number 1 above). Only Functions with no return type can have an unlimited amount of linked Listener Blocks

    Thanks again for all the amazing stuff coming to C3.

  • You do not have permission to view this post

  • You do not have permission to view this post

  • Yeah I agree it's better to seperate suggestion in most cases if they are really different but I also feel like #1 and #2 are somewhat related.

  • EDIT : I released a Construct Tool allowing to do this and much much more :

    JSON+ overboy.itch.io/construct-3-json-plus

    Tagged:

  • Yeah true it can be useful for some usecases, but I'm pretty sure some people requesting for Hierarchy opacity don't realize this wouldn't be what they expect and it wouldn't solve their current issues.

    As I said at the end of my previous post, I think the other use cases should be done with Layers and would be really easier to do with Instanciating + Reordering Layers at runtime.

  • Don't forget Hierarchy Opacity is more complex than it seems. It's not just about syncing stuff.

    I'm pretty sure we all want Construct to consider a whole Hierarchy as a "single image" when it comes to opacity.

    If I have 3 objects stacked on top of each other and part of the same Hierarchy. If the Hierarchy is set to 20% opacity, I don't want to see each of those Objects through each other (like if each Object had a 20% opacity individually).

    We probably want the whole hierarchy to be at 20% opacity, not individual parts.

    Also what if one of the child had 50% opacity and then its parent changes its own opacity from 100% to 10% opacity ?

    However if one day Construct had this possibility to render a Hierarchy as a single merged stuff, it would be nice.

    Maybe it would also allow us to have effects applying to the whole Hierarchy as if it was a "single image/object".

    But then it raises other issue regarding ZOrdering with other Objects that are not part of the Hierarchy. => most probably this "render as single image Hierarchy" option should be an option we don't want in other cases. And the ZOrder/Layer of the whole Hierarchy would be the ZOrder/Layer of the parent. (Child original ZOrder/Layer wouldn't be useful anymore, except for defining the ZOrder for each Objects that is part of the Hierarchy and maybe the position if Layers have different Parallax/Zoom scale)

    => it looks a bit like a rabbit hole

    A probably easier way to achieve all those things would be to add the possibility to instanciate and reorder Layer at runtimes