Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Managing thousands of objects
#1
I have a game where the user can place many objects, potentially thousands, and also use a couple of ropes which should then react to these. The issue is, the ObiUpdater becomes incredibly slow looping through all the obi colliders and updating them. It reaches easily 500ms for only 4000 objects on a high-end pc per frame. 

What are recommendations to handle such scenes? Are there optimization tricks or settings I can tweak?
Reply
#2
(20-02-2023, 09:31 PM)ImpossibleRob Wrote: I have a game where the user can place many objects, potentially thousands, and also use a couple of ropes which should then react to these. The issue is, the ObiUpdater becomes incredibly slow looping through all the obi colliders and updating them. It reaches easily 500ms for only 4000 objects on a high-end pc per frame. 

What are recommendations to handle such scenes? Are there optimization tricks or settings I can tweak?

Hi there!

Colliders are Unity components, as such they can't be accessed from any thread other than the main one so their data must be copied to NativeArrays in order to be processed in parallel during the simulation. Updating data for 4000 colliders requires looping trough them in the main thread, there's no way around this.

Having that many colliders active at once is probably a sign that you need to divide your scene into smaller chunks. Depending on how your game is designed, a simple approach could be placing all colliders in a grid and only adding ObiCollider component to those in cells that overlap the solver's bounding box.

This said, 500 ms to loop trough 4000 objects copying just a few bytes worth of data for each seems excessive. I would guess there's something else at play there, probably either death spiraling or some other performance pitfall. Could you share profiler data for this?

kind regards,
Reply
#3
Just did a quick test: updating and calculating collisions against 4000 overlapping box colliders in a 2013 Macbook takes roughly 13.5-14 ms/step for me (this happens in the BeginStep method, seen in the profiler):

[Image: od0YQiF.png]

With the default timestep settings (fixed timestep 0.02, max timestep 0.33) it causes the engine to take two physics steps per frame, for a total time of 30.4 ms/frame including rendering all 4000 boxes.

500 ms/frame is more than an order of magnitude slower, specially considering A) colliders are not usually overlapping but spread out over a larger area and B) you're using much more powerful hardware so there's definitely some other issue at play in your case.
Reply
#4
The 500ms result from the CPU solver of obi, since I still cannot activate burst (see other thread). That might be the reason for this order of magnitude. My game is a physics game where basically anything can happen in a non-localized area, e.g. a cannon shoots a ball to the other side, hitting something there, causing a rope to move etc. Is there a way to tell the solver or have the solver only consider colliders in the ropes area of influence? I have objects many meters away which could never interact with it except if by some physics force thrown into the vicinity. Having some regular (not per frame check I guess) test of collider distance and only waking up for the objects that are indeed close could give a huge boost.
Reply
#5
(28-02-2023, 03:14 PM)ImpossibleRob Wrote: The 500ms result from the CPU solver of obi, since I still cannot activate burst (see other thread). That might be the reason for this order of magnitude. My game is a physics game where basically anything can happen in a non-localized area, e.g. a cannon shoots a ball to the other side, hitting something there, causing a rope to move etc. Is there a way to tell the solver or have the solver only consider colliders in the ropes area of influence?

The solver already only considers colliders close to a rope during simulation. However, Unity must update the position of all colliders that have a ObiCollider component and this must happen in the main thread, this is what the cost comes from.

Simplest solution for this is the one I suggested before: group them by spatial proximity (using a regular grid, for example) and only add the ObiCollider component to those collider in zones that intersect the solver's bounds.

This is the same approach you'd use in any game where thousands of objects must undergo some sort of update. For instance if your game took place in a castle full of rooms, you would not update every object in all rooms all the time: you would only update those in the room you're in, or a few rooms adjacent to it.
Reply