Will the top level design be removed in C3?

  • The reason objects aren't pickable until the next top level event is an architectural detail. It actually used to make them pickable immediately, but it led to crash bugs, so the existing system is a workaround to those bugs. The problem is that to make an object pickable it needs to be added to the set of instances in the object type, but conditions iterate this set when evaluating conditions. For example think about this event:

    + For each Sprite

    -> Create "Sprite"

    "For each Sprite" will iterate every Sprite instance, but the event itself modifies the set of Sprite instances. It's difficult to handle this case correctly without introducing a global performance impact to the event system, because every condition has to constantly check if the set of instances it is iterating has changed. (It's also interesting to think about how this event would turn in to an infinite loop if it also iterated the instances it just created!)

    The actual bugs IIRC were even more complicated, involving sub-events and function calls, which ultimately led to an instance being created half-way through the evaluation of a condition that was testing the set of instances in that object. In order to handle this case, created objects are picked (so you can access them in the event immediately), but they are not added to the set of instances until the end of the top-level event, which guarantees no conditions are iterating them. I thought about only doing this when this mid-iteration case was specifically identified as happening, but I thought it would be better to be always consistent rather than doing something subtly different depending on the parent events/function call context which would make for some pretty maddening debugging. So created instances don't "really" exist until the next top-level event, although they are picked.

    It's hard to see how this could really be different. We could make it only do the workaround when it needs to, but being slightly inconsistent depending on the context is generally a terrible idea, because in practice it means unpredictable consequences. We could add them to the instance lists immediately, and then a bunch of games start crashing. Or we could add a check to every condition to verify if the instances change while it is iterating them, which adds a performance overhead to every event. Given these options, leaving it until the next top level event is the best option IMO.

    BTW the stated goal of C3 is to rebuild the editor and keep the same runtime, so this is not really the kind of thing we intend to change anyway in the scope of that project.

  • Ashley What do you think about my idea of creating temp groups while picking, by assigning them to selected group?

    "In the picking selection window, just add txt input where you place a name of "set pick group" , or even just a dropdown under same name with groups "A" "B" "C" and "D"."

    This is not related to picking at creation, but it would be useful to pick few objects of the same type, and it would be better then using families.

  • + For each Sprite

    -> Create "Sprite"

    "For each Sprite" will iterate every Sprite instance, but the event itself modifies the set of Sprite instances. It's difficult to handle this case correctly without introducing a global performance impact to the event system, because every condition has to constantly check if the set of instances it is iterating has changed. (It's also interesting to think about how this event would turn in to an infinite loop if it also iterated the instances it just created!)

    BTW the stated goal of C3 is to rebuild the editor and keep the same runtime, so this is not really the kind of thing we intend to change anyway in the scope of that project.

    It had of course crossed my mind since you have already stated in the C3 presentation that C2 projects are compatible with C3 that this of course could cause some problems if something like this were redesigned.

    But as I suggested with the temporary objects/data, couldn't that be a viable solution, for in the example that you made with the For each Sprite, Assume you have 5 Sprites (Existing instances), So for each of these, a temporary object is created. So even though there now are 10 objects in total, only 5 of them are on the "Existing instances" list and 5 is on a "temporary instance list". So at the point the for each runs it will only include the 5 "existing instances" as the temporary ones are not currently sharing this scope. So imagine you apply yet another For each Sprite after the last one, it actually knows at this point that 10 exists as it include or checks any former created temporary lists, so it will create a new temporary instance list which will hold the new temporary instances, in this case 10. So to put it visually, it would look something like this:

    5 (Existing sprites list)

    5 (Temporary sprites list 1)

    10 (Temporary sprites list 2)

    So still you could update these objects as if they were all part of the same instance list, but would make some of the changes to the "Existing sprite list, some to temporary list 1 and 2. When the process at some point hit the top level all instances are then moved to the normal "Existing list". But whether that would ruin the C2 projects or even work im not sure of, at least not if some sort of fail save weren't added. Maybe it could know that if its an original C2 project it could simply not make use of temporary lists, or it could ask the user if they wanted to update there project to a C3 one, and what problems might occur. So users are left with both options.

    Would something like that be possible, assuming that this was on the agenda for C3, which you of course have already mentioned that its not?

    Because if you look at the example I made earlier in this thread, and assumes that for some reason this was an important game mechanic. How would you go about solving it, with the way that it currently works, because I don't find it an unrealistic scenario?

    Anyway cheers for sharing your thoughts on this matter.

  • The "temporary sprite list" is pretty much exactly how it works already, and it moves those instances to the main list at the end of the top-level event. However if every condition also checked the temporary list as well as the existing list, that would add a performance impact to every event again, since now every condition has to check two lists instead of one.

  • The "temporary sprite list" is pretty much exactly how it works already, and it moves those instances to the main list at the end of the top-level event. However if every condition also checked the temporary list as well as the existing list, that would add a performance impact to every event again, since now every condition has to check two lists instead of one.

    I see.

    However im a bit confused why it would hurt performance. Because wont it be the same in the end anyway? For example we create 100 objects which are transferred to the main list at the end of the top level, and this is what confuse me. Because during the next tick, all 100 objects will be on the main list so whatever condition that would check these objects would apply to all 100 objects. So the performance impact happens from the period of creation to the end of top level, when working with the temporary list?

    Since im not 100% sure to be honest what these lists are, but assumes you mean they are stored in memory? it might be what confuses me a little. Because if we assume that in our game we have at max 1000 objects at a given time and for the sake of argument the temporary list is checked as well. So we have two scenarios, this is just so I understand what you mean:

    A: There are 800 objects on the main list and 200 on the temporary list

    B: There are 150 objects on the main list and 600 on the temporary list

    So if I understand you correct, the performance impact would be higher in scenario B than A, if the temporary list was checked as well?

    And to further extend this and we remove the check of the temporary list, using the same scenarios.

    Then during the "tick" of creation until the end of top level, you would have better performance in both scenarios due to not checking the temporary list, but the next tick. You have 1000 objects in scenario A and 750 in B. Hope you see what I mean when I ask if its not the same in the end? or did I misunderstand you?

  • It's slower simply because it's more work to iterate two lists than one, and that overhead would apply to every single condition in the project. Currently the engine uses a simple flag to indicate that there are instances on the temporary list that need to be transferred, and checking a flag between every top level event has negligable overhead.

  • It's slower simply because it's more work to iterate two lists than one, and that overhead would apply to every single condition in the project. Currently the engine uses a simple flag to indicate that there are instances on the temporary list that need to be transferred, and checking a flag between every top level event has negligable overhead.

    What about the idea of having temp grouping when picking, to make diversifying same objects when picking easier?

  • It's slower simply because it's more work to iterate two lists than one, and that overhead would apply to every single condition in the project. Currently the engine uses a simple flag to indicate that there are instances on the temporary list that need to be transferred, and checking a flag between every top level event has negligable overhead.

    This is probably a stupid question, anyway . But instead of using a temporary list couldn't the objects in the main list just contain a flag as well marking them as existing or as temporary and based on this they would be handled differently, maybe the flag could keep track of where in the scope they were created, so the problem you mentioned about infinite loops wouldn't happen. Or is that not possible? Because that way you wouldn't have to spend resources transferring, I would guess. You could just change the flag for all existing objects at the end of top level if that makes sense or would that still be worse than it is now, if possible?

  • As it stands, the only real performance overhead applies at the end of a top-level event that created new instances, when it transfers the temporary list. If every condition checked both lists, all conditions would have a performance overhead, regardless of if the event created new instances or not.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • Ashley ,

    Is it possible to mark where an instance was created, then skip every event until it gets back to the place is was originally? That way it would have the instances updated, but nothing will have changed, so it can then continue with the new instance. I would imagine that skipping everything would be quicker than having everything check the lists.

  • Ashley ,

    Is it possible to mark where an instance was created, then skip every event until it gets back to the place is was originally? That way it would have the instances updated, but nothing will have changed, so it can then continue with the new instance. I would imagine that skipping everything would be quicker than having everything check the lists.

    Why do you need to pick just created instance?

  • > Ashley ,

    > Is it possible to mark where an instance was created, then skip every event until it gets back to the place is was originally? That way it would have the instances updated, but nothing will have changed, so it can then continue with the new instance. I would imagine that skipping everything would be quicker than having everything check the lists.

    >

    Why do you need to pick just created instance?

    An example is If you have to spawn an object based on some value of another newly created object and you then have to use those information for something else. But there are several places where this can cause problems, that are not that easy to give examples of. So guess its just as much this way of creating objects that, if it could be changed would be nice for C2/3, as it would make it easier to use, but also potential problems that you will have to workaround could be removed.

    But if you look at my example on one of the other pages, it shows how it occurs and what problems it causes. But since that is a very simple example, it can become a bigger problem in larger projects, where you might have thrown in waits etc. But in general, at least when I design my projects I always try as best as I can to avoid having to solve things with waits. But in some cases its just not always possible in my experience. But its very difficult for me at least, to troubleshoot or even post my projects on the forum, because they are rarely less than 2-3000+ events so I don't expect anyone to care looking through the code trying to troubleshoot. But also its very difficult to recreate something that occurs at some point during such a huge project. So even picking out a part of where the problem occurs and trying to recreate it in an example to be posted on the forum, its very likely that it wouldn't reflect the actually problem in a correct way.

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