0 Favourites

Big levels and FPS

This forum is currently in read-only mode.
  • I'm making a game with some large levels, but the more stuff I add the lower the fps drops. I am using the line of sight behaviour (set to 50px) , but only every ~100ms, and if within a certain distance. My question is, how does construct handle objects that are off screen, and could it do with an option to ignore some objects that are VARIABLE DISTANCE off the screen?

  • Construct 3

    Buy Construct 3

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

    Buy Now Construct 3 users don't see these ads
  • How many objects are you talking about here? The size of a level itself has nothing to do with how fast it runs, it's just essentially numbers that control scrolling - so it's entirely the object count and the processing the game does. To see if it is the LOS, try (backing up your game then) deleting the LOS related stuff and seeing if it runs much faster. If it doesn't, look elsewhere.

    Objects offscreen are not drawn - and that's about it. They'll still be processed by events, check collisions, etc. Pathfinding with the RTS movement can be a CPU hog too if used wrong, are you using that?

    Also, if you're using shaders, which ones are they? A lot of shaders can slow down performance, especially on lower end cards.

  • There are about 1500 objects, and that is holding back, it could easily be double that if I wanted to saturate the level entirely.

    I'm not using RTS movement.

    Am I right in assuming off screen shaders shouldn't affect performance?

    With simulate shader 0.0 on I still get stuck around 30fps. (My computer isn't that bad - 3ghz dual core etc, so I'm worried about other people playing it.)

    Disabling LOS events doesn't change FPS at all either

    The only thing I've come across that increases FPS significantly is deleting a bunch of objects.

    In this situation where I have loads of for each object loops, and other events that may get a lot more intensive the more objects I have, I think it could benefit from leaving out objects that are far away (since they'll be stationary, and miles away from any action anyway). Obviously this would be optional.

    I can get around this by just chopping up the levels and having more of them, but it's not ideal, and may not be as easy with another game.

  • If its events you might be able to speed things up by using conditions which only pick objects that are on the screen or within range of the player. However perhaps theres a particular area in the events when is demanding on the cpu, like nested for each object loops...

    You say you have over a thousand objects...are they all scenery or are some particles and stuff? Maybe if you're able to send the cap file we could have a look over it.

  • Yeah, I'm just taking shots in the dark here unless I can see your .cap. Send it over and I can run it through a profiler.

  • I have had a brief look at the .cap you sent me. I'm replying here because some of the information might be useful to others.

    To be honest with such a large .cap, it's difficult to make sense of that many events, and I did run it through a profiler - which said the 'For Each' system condition is using the majority of the processing time. I don't think it's the line of sight object, although you have nearly 200 objects using line of sight - even at timed intervals, 200 line of sight intervals might be a fair bit of processing. To be on the safe side, you should minimise the CPU overhead by only checking line of sight queries for objects within a certain range, objects just on-screen, etc. If you do this, remember conditions are checked in top to bottom order, ie.:

    + Enemy is on-screen

    + Enemy has line-of-sight to player

    This event is faster, because it picks the N objects that are on-screen, and does line of sight checks just with those objects. If you order it:

    + Enemy has line-of-sight to player

    + Enemy is on-screen

    This processes a possibly expensive line-of-sight operation for all objects - on and off-screen - then of these, discards the ones offscreen, which is a waste of the processing power you just spent on them.

    Still, judging by the profile results, you have a very CPU intensive 'for-each' loop somewhere. I can't find it with all the events you have, but hopefully the information is useful to you. An ordinary 'for-each' event is usually very fast, even with thousands of objects - I think you must be nesting loops somewhere in a very inefficient manor. For example:

    + For each A

    + For each B

    iterates A x B instances, and

    + For each A

    + For each B

    + For each C

    iterates A x B x C instances. If you have 500 instances of each, this is the difference between 500 iterations with a single for-each, and 125 million iterations (!) with three nested for-eaches (thats 250,000 times as much work). So you can see how nesting exponentially creates more work for the CPU with high object counts - you should be careful with code like that.

  • What is this profiler you're using, Ash?

  • Just thought I'd pop a note in here that you can use the Profiler plugin to time segments of events, in ticks or in MS, in order to optimize your events.

  • What is this profiler you're using, Ash?

    AMD CodeAnalyst. There are better ones, but CodeAnalyst is free. Only works on AMD processors but Intel have their own equivalent, but I've forgotten what it's called. Profilers automatically tell you which functions in the source code the CPU has spent most time executing. You need the Construct source code to use it (what a surprise, you can get it too!), and to build with debug symbols (/DEBUG) so the profiler has access to function names.

    Then you run under the profiler. In this case, SystemObject::cForEach had the majority processing time, hence the above conclusion.

  • Thanks Ashley that's helpful, I'll attempt to hunt down any nested loops, (hopefully they're not necessary). I did try to do the LOS events like you said, even putting them in subevents to make sure.

    I guess what I was suggesting isn't all that useful if it's just my poor coding, if it can be done through events.

    One more thing, are pick by comparison events as processor consuming as for each object loops? (if they loop through each object checking the expression) because I may have those and for each object loops nested together.

  • One more thing, are pick by comparison events as processor consuming as for each object loops?

    No, it's an ordinary filtering condition and doesn't run repeats. Nesting them doesn't cause further exponential processing - just further filtering of the handful of objects that are picked in that event. It is the repetitions run by the looping conditions like Repeat, For, For-each and so on that cause exponential processing when nested.

  • That's nice.

    I do have some nested loops for minimising an expression, these could well be the cause of the lag. Seems like a decent time to request the "pick by highest/lowest expression" I've requested a couple of times to fix this really nicely.

    EDIT: now fps is ~80 at the start (hell of a lot better than 30) when I disable this event it jumps up another 20ish, clearly an extremely inefficient way of doing it, pick highest/lowest would be really nice.

    Adding pick by distance<2000 to every for each enemy loop seems to have worked. Thanks a lot that was a huge help.

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