Search Unity

Dynamically loading thousands of objects based on proximity to player

Discussion in 'Scripting' started by malkere, Dec 27, 2019.

  1. malkere

    malkere

    Joined:
    Dec 6, 2013
    Posts:
    1,212
    The title pretty much says it, and you'll see it in a lot of games, objects loading in closest to the player first, gradually spreading outward instead of all at once to save on framerate/load times.

    I understand the basic concept, was just curious if anyone wanted to share their two cents on how to go about it, or is aware of any youtubers/bloggers than have touched on the subject. Currently I just blast everything on all at once, and it causes a pretty nasty hitch on lower end computers, albeit infrequent.

    1. Player spawns, could be anywhere (open world).
    2. 2km^2 of terrain full of objects spawns around the player.
    3. Objects send message to manager object informing of presence, location, and loading priority.
    4. Manager sorts objects into chunks (50m^2?)
    5. Manager sends enable calls to objects in order of priority (low/med/high) as well as chunk distance from player, spread out to some flexible maximum number of objects per frame.

    Further optimizations would of course be to pool things as much as possible, and to use component enable/disable instead of GameObject enable/disable.

    Cheers on any input.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,727
    Sure, first step to any performance improvement is to measure it.

    If you don't measure something, you can't know how to change it meaningfully.

    Open the Unity profiler window and get familiar with profiling, especially profiling on actual target hardware. It's a pretty big field of techniques, but luckily often the first steps you take will yield the biggest most noticeable results. Google up profiling in general for other tips.
     
  3. malkere

    malkere

    Joined:
    Dec 6, 2013
    Posts:
    1,212
    Thanks, I'm well aware of how to profile. Profiling will simply show what is obvious, that Unity simply cannot spawn/turn on thousands of objects at once without a big pause, and that's not going to change, profiling out tiny improvements per script/component or not.

    This is more of an architectural question as regardless of the above, some games, like mine, need to handle thousands of objects on the fly. Approaches to spreading the management of streaming those objects in, over time, to smooth the performance is my question/discussion. Simply loading things up via an arbitrary queue could see things hundreds of meters away spawning in while the plants right in front of a player do not, thus distance management. Plants being less important than say a treasure chest, thus priority management.
     
  4. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,776
    Did you hear about pooling objects and LOD?

    Another step, could be chunkyfing the world and load stuff peer chunk. Otherwise called spatial mapping/division, like quadtree, octree, etc.

    There is also scene async streaming, something like that.

    Jobs on higher level.
    And eventually ECS.
     
    malkere likes this.
  5. malkere

    malkere

    Joined:
    Dec 6, 2013
    Posts:
    1,212
    Pooling and LOD are absolutely in use. I think "chunkifying" is the big one, but ways to manage those chunks is what I'm asking about. Actual logic flow of object to spatial mapping management interactions. Again, I think queuing "chunks" based on their position in regards to the player and cycling through objects by a set of priority keys is the best way to go.

    ChunkDistance0 Priority0
    ChunkDistance0 Priority1
    ChunkDistance1 Priority0
    ChunkDistance1 Priority1
    ChunkDistance0 Priority3
    ChunkDistance1 Priority3
    ChunkDistance2 Priority0
    ChunkDistance2 Priority1
    ChunkDistance3 Priority0
    ChunkDistance3 Priority1
    ChunkDistance4 Priority0
    ChunkDistance5 Priority0

    Something like that. Perhaps with a max of 10 GameObjects per frame, or something like that, pending testing.

    I suppose I didn't mention this is entirely procedural, so loading scenes async, and other "static" / baked methods are not applicable. Players can run around freely for millions of kilometers (and do) with the world loading around them using deterministic seed based noise.

    Jobs can certainly help prepare the data, but you can't instantiate objects in Jobs if I'm not mistaken. I do use threads to prepare what's where.
    ECS would probably be a great addition to logic handling and reduced overhead during instantiation, but I'm sticking to 2018 LTS for now.
     
    Last edited: Dec 27, 2019
    doarp likes this.
  6. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,776
    Spawning 10 objects is nothing for Unity, even instantiating.
    If we talking about thousands, that different story. But the trick is, of reusing objects from pool, rather destroy and instantiate constantly.

    Regarding getting data from bar chunks, this is where spatial mapping comes into play. It will allow you to grab data from near 'segments' or call chunks.

    But indeed, you can not instantiate in Jobs. You need do that on main thread. But then again, that only issue, if you loading lots of objects for the first time. Later you juz reuse them and position/scale accordingly.

    ECS could make thing more efficient in high volumes. But depending if you want to go that route already.