For each optimisations

0 favourites
  • 14 posts
  • As you know For Each works as a system loop, and can be cpu intensive if you have many instances.

    I would like to propose an addition that would alleviate some of that.

    Basically instead of picking each instance every tick, you pick a single, or loop over a smaller number of instances like an array each additional tick. For example if you had a thousand instances you do a mini "for each" over say a hundred in one tick, the loop over the next hundred in the next tick, then repeat at the end.

    I know that you can already do this with "pick nth", or via instance variable, but as a system command it would alleviate some of the confusion for newer users who may not understand how For Each is supposed to work.

    I think the only real concern would be how to iterate, ascending, descending, and other evaluations such as y,z, etc.

  • 'For each' only iterates instances that met the prior conditions. So you can already do this by picking a subset of instances first, then using 'For each'.

  • Yes, but getting new users to understand that, and figure out how to set up the filtering as well as repeating the indexing.

    Which is something of an undertaking even for an experienced user.

  • It sounds like this feature will just be re-inventing an existing feature a different way then, which tends to be a waste of time, and actually increase confusion since now there's two ways of doing the same thing, so which should you use and why?

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • The use case is for when the number of instances processed in a single tick would bottleneck the system.

    When it became clear that sorting a z based on for each and y was too inefficient you added "Sort Z Order"

    We need a better way to handle for each.

  • "Sort Z order" is a different case. It made an improvement to the algorithmic efficiency. This doesn't sound like it does that.

  • Ok, well how about better ways of filtering?

    We don't have many great ways for that kind of picking.

    Its either by variable, or messing around with the iid.

  • Conditions already do filtering. I don't want to have to reinvent the wheel and have some kind of second system that also does filtering, but differently.

  • Ok, I tried.

  • As mentioned previously, I think Picking is already intuitive....But

    I have seen the Majority of new questions about "For Each" which come from the fact that

    if you don't know anything about coding and loops, which is supposedly what the appeal of

    C2..3 is, then most people associate "For Each" to mean in literal English,

    "For Each once".

    Example "For each Person, I will give a Cake.", not "For each person I will give a cake, when I have finished, I will start again and give everybody a cake."

    So I think It would be beneficial, if you had a selection, Just like the Timer Behaviour.

    For Each (Looping for each instance)

    For Each (Only Once for each instance)

    Obviously the first option would be, legacy backward compatible.

    This might save a lot of frustration, from newbies, from a non coding background.

  • I think creating variants of the same condition is actually more confusing for beginners. Now you have to explain what the differences are between the two, why you need both, and when you'd pick one over the other, instead of just explaining one condition.

  • I think a work around here might be a seperate object, third party perhaps, that schedules objects and instances like a stack. It would work essentially like the Timer Behavior, but sets the timing based on the stack, and fps.

    I think I've read about a system like that in other engines, like an instance bank, or sprite bank.

    Although the anti-bottlenecking may just be coincidental.

    I would say just use the Timer Behavior, but it would need to work with multiple objects.

    In the end you would likely end up having to use a for each anyway.

    Then again the bank would be a loop as well, and would be useless if it slows things down.

  • Even though it is already possible and we currently have:


    *For each

    *For each(ordered)

    *Condition met



    Not sure if it's complex but, something like: For each(over time) : Loops over instances by specified time interval'tick'.

    So when user has 550 object

    For each object

    time: (7)

    So each tick loops over around ~79 instance

    This indeed could make some cases simpler to handle or create.

    So i can't agree this is confusing.

    Sure this will consume dev time, which is already possible.

    This is somewhat re-inventing the wheel, but to shift complexity over scirra side.

    This also sure will cause errors and bugs.

    Overall, would be nice to have, like a lot of other features suggested.

    My 2 cents (:

  • I also think the principle of running on ranges of instances at different ticks is not a good way to solve the problem. It potentially raises more tricky problems:

    - it's a subtle way to introduce framerate-dependent logic. It's essentially like saying "every N ticks", which is framerate dependent. On a high refresh rate screen the "every N ticks", or "for-each across N ticks" will run faster, and this can produce a different and potentially unwanted result, with parts of your logic running faster than they ought to. Using dt to avoid this is also extra-tricky, because you really want a time step across multiple frames. So you can end up introducing hard-to-find and hard-to-fix bugs in your project that won't show up until later.

    - it's very difficult to schedule efficiently. On a high-end machine you might want to go through 1000 instances per tick. However on a low-end machine that might still kill performance. If you reduce the number though, the high-end machine has wasted capacity - it could easily be processing many more instances but you had to put in an arbitrary limit for low-end machines. So now high-end machines have to pretend to be a low-end machine, cancelling out their performance benefit. Determining the right number depending on the hardware is a notoriously tricky problem. This is compounded when you consider: should it go through N instances per tick? e.g. if you process 100 instances per tick regardless of the total count, then you end up with increasingly long latency to process all instances (at 60 FPS, it takes 33ms with 200 instances, or 1000ms with 6000 instances). Or do you go through all instances per N ticks? Now you have an unbounded processing limit again, so it can still end up slow, defeating the purpose of doing this.

    I think there are several different existing approaches you could use that avoid these problems completely. For example you could use a boolean instance variable to opt-in instances to processing with a certain event. Or you could only process objects on-screen or nearby. Or you could find a different way to approach the problem that doesn't involve heavyweight for-each loops. It depends on exactly what you're doing.

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