If you use solid behaviours, you need to see this.

  • So I was goofing off with some solids and ran into a head scratcher. The more solids I added to the layout, the slower it became... by a lot. So, I created this little test project. Have a look and you'll see what I mean.

    twistedvoid.com/c3examples/collision1

    *Edit

    Here's a new version compiled in r161 after the patch for a comparison:

    twistedvoid.com/c3examples/collision2

    *end Edit

    There are 4 tests that are conducted and I recommend running them in Chrome. If you want to see how bad Edge is when running a Construct project, try these tests with it.

    Test 1: Creates 3000 ants on the layout. This is the control. Each ant has a 4 frame animation. It has 3 behaviors: Bullet, pathfinding and bound to layout. In particular pay attention to the time at the top. This is the time in ms it takes to perform a tick. Depending on your machine, you shouldn't see it change a lot even when it gets close to 3000 ants on the screen.

    Test 2: Same conditions as above with this following exception: 20 square sprites with the 'solid' behavior have been added. Again, watch the timer as it gets closer to 3000 ants.

    Test 3: This is the serious wtf. Same ant parameters as the control except that the 'solid' behavior has been added to the ants however, it's disabled. This test only has 500 ants and if you watch the timer again, you'll see why it's only 500.

    Test 4: Same test as above except, the ant's 'solid' behavior has been enabled (more or less to prove that it was disabled in the previous test.) This test only has 300 ants and there's a good reason. 500 ants will turn most any machine into a snail. This test, has pretty predictable results.

    The second test is the one that clued me in to the 'solid' behavior and the affect that even a few of them can have on a project. The 3rd test was totally unexpected. Why should there be that much lag caused by adding a disabled behavior????

  • That would be a bug.

  • I don't have time to run the experiment right now, but is a linear drop in performance, or is there a key point that everything goes awry?

    Interesting find regardless, here's hoping the fix results in an engine wide soup up

    EDIT//

    Just ran the test (damn curiosity) can confirm test 3 and 4 turned the game into a PowerPoint presentation past 200 ants

  • No difference between tests 1 and 2 on my laptop, all the way to 3000 ants

    With solid behavior added to ants, things do deteriorate pretty quickly.

  • No difference between tests 1 and 2 on my laptop, all the way to 3000 ants

    With solid behavior added to ants, things do deteriorate pretty quickly.

    Did you try running it with MS Edge? On my 8 core AMD in Chrome there was like a 3-5 ms drop in performance between the first and second but it stayed around 17ms. Running Edge... wow... it sucked.

  • One of the things I paid attention to while creating this test was collision checks when running in debug mode.

    In the first test with no 'solid' object to collide against, it still peaked at around 180 collision checks per tick. So, even though there was nothing to collide against, it still performed collision checks. I thought this was caused by the anthill which had 0 behaviours but enable collisions was ticked on. So, I set it's collisions enabled to false on the anthill and still got the 180 collision checks. No idea what it's checking collisions for.

    The second test, with just 20 blocks with solid behaviour... get this... 90,000 checks per tick at ~3000 ants. That was over 3.5 million checks per second. With collisions disabled on the block sprite, 0 collision checks.

    The third test... boggle... ZERO collision checks. I ran this test also with the collision enabled set to false and, as expected, zero collision checks and it ran smoothly. So even though it's saying zero collision checks, apparently it still is.

    The fourth test, expected but not this big, 500,000 collision checks per tick at peak. That's 1,666 collision checks per tick, PER ANT, 7.5 million per second. And, I ran this with collision disabled and it too has zero collision checks and ran smoothly.

    I ran one other test with the solid behaviour disabled on the blocks and, this was kinda unexpected but expected, zero collision checks.

    I'm pretty sure my test is accurate. I can't explain why the ants with solid disabled caused such lag but the block sprites with solid disabled didn't. My only guess is, that in the second test there aren't enough block sprites to make a visible difference. If you notice in the third test, it seems to run ok till ~100 ants are running around before the lag starts to hit.

  • Do you have "Bounce off solids" set in Bullet behavior? I can reproduce the same issue, but only when I set Bounce off solids=yes for ants.

    So it looks like a bug, I'm guessing Bullet still tries to check collisions with disabled solids.. (or rather it checks if Solid is enabled 300*300=90000 times per tick)

    EDIT: Ashley Here is my project, at ~1000 ants fps drops below 10. But if you remove disabled Solid behavior, it runs at 60 fps with 3000 ants.

    dropbox.com/s/qi2o2hzl5aji851/BulletAndSolid.c3p

  • Performance could well depend entirely on the specific events you're using, but unless you share an actual project file nobody can see that.

  • Performance could well depend entirely on the specific events you're using, but unless you share an actual project file nobody can see that.

    twistedvoid.com/c3examples/collision1/Collision1.c3p.

    Do note there are some extra sprites and some checks for those sprites in the ant's wondering routine. I started with another test I created and just couldn't be bothered to remove them. But, because those checks are in all of the tests it still should provide a comparable baseline.

  • Do you have "Bounce off solids" set in Bullet behavior? I can reproduce the same issue, but only when I set Bounce off solids=yes for ants.

    So it looks like a bug, I'm guessing Bullet still tries to check collisions with disabled solids.. (or rather it checks if Solid is enabled 300*300=90000 times per tick)

    EDIT: Ashley Here is my project, at ~1000 ants fps drops below 10. But if you remove disabled Solid behavior, it runs at 60 fps with 3000 ants.

    https://www.dropbox.com/s/qi2o2hzl5aji851/BulletAndSolid.c3p?dl=0

    I did have bounce enabled. So, disabled it and ran the tests again.

    Test 1: 17ms per tick w/3000 ants. 0 collision checks.

    Test 2: 22ms per tick w/3000 ants. 26,548 collision checks per tick which didn't change from 0->3000 ants!?

    I saw peaks of 1.5+ million checks per second.

    Test 3: 95ms per tick w/500 ants. 0 collision checks. Still the huge lag even with solid disabled.

    Test 4: 62ms per tick w/300 ants. 300,000 collision checks per tick witch hit the 5+ million/sec mark

    So, in my tests, bounce disabled made no significant difference.

  • dropbox.com/s/qi2o2hzl5aji851/BulletAndSolid.c3p

    Much more refined than mine and the same results. Thanks for 'cleaning up' my test ;). My old laptop hit 5fps before 1000 ants.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • dropbox.com/s/qi2o2hzl5aji851/BulletAndSolid.c3p

    Great example dop2000 - my home PC has a RTX 2080Ti, 32GB RAM and an i9-9900k processor - past 1000 ants the fps drops to sub 20 before falling to 1-2. Definitely something happening there.

  • So, in my tests, bounce disabled made no significant difference.

    That's because you also have Pathfinding behavior with obstacles=solid and regenerating map on every tick.

    Of course, you shouldn't regenerate obstacle map on every tick in a real game, it's a slow operation. But this test shows that Pathfinding has the same issue as Bullet - even though Solid is disabled for all ants, they are still getting processed by "Regenerate obstacle map" action.

    Here is a small demo:

    dropbox.com/s/pp0cpt7zgt6edbm/PFAndSolid.c3p

  • Not to debunk or anything but just out of curiosity: why would I give the solid behavior to hundreds of constantly moving object? When trying other engines everynone tells you to avoid using solid objects as much as possible. Interesting test though :)

  • I think this comes down to the sequence of how collisions are checked in the engine. If you check for all solids colliding with a sprite it goes along these lines:

    1. Collect all nearby objects using the Solid behavior (using collision cells)
    2. Run through list of nearby objects, skipping any disabled Solid behaviors (or with mismatched collision filtering tags)
    3. If solid collision enabled, test for overlap (which goes through its own process of bounding box, bounding quad, then collision poly, to try to use quicker checks to avoid a full poly check)

    If you have 1000 sprites all checking for collision against themselves, then that requires 1 million collision checks per tick. Obviously this is extremely demanding and even the tiniest variations in how the engine handles this will produce measurable performance differences.

    If the objects don't use the Solid behavior at all, then the process stops at step 1 (it gets an empty list). If the objects use the Solid behavior but they are all disabled, the process stops at step 2 (it collects a list of solid behaviors, then skips them all because they're all disabled). If the objects use the Solid behavior and they are all enabled, then it proceeds all the way to step 3.

    It kind of has to work like this, since the collision cells optimisation works by grouping object types in to regions of the layout for handling any type of collision (not just solids), which necessarily does not take in to account any enabled/disabled state for behaviors. So yes, in this case you can measure a performance difference between no solid behavior, and a disabled solid behavior. In practice though I don't think this will affect most games, unless they do something similar involving millions of collision checks per second (which is already an obvious thing to optimise in your game).

    While profiling the project I found an easy way to optimise the checks for disabled solids, which on my system boosted one test with 1000 objects from ~18 FPS to ~30 FPS, so that should help a bit. But checking for collisions between all combination of hundreds, or thousands, of instances is always going to be incredibly CPU intensive and is something that generally ought to be avoided. Also if these objects were spread across a large layout, collision cells would be more effective at eliminating collision checks for far-away instances.

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