Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Spawning entity prefabs via EM is much slower than subscene

Discussion in 'Entity Component System' started by WildMaN, Dec 28, 2021.

  1. WildMaN

    WildMaN

    Joined:
    Jan 24, 2013
    Posts:
    127
    I've always used subscenes and put my predefined prefabs there, but now I need to spawn some on the fly. And to my surprise it takes waaay too long to spawn an Entity prefab with ~100k children entities, EntityManager.Instantiate takes around 200ms on my PC and ~500ms on Android. The same prefab being put into an empty SubScene loads up instantly. I cook my prefabs the usual way with DeclareReferencedPrefabs and store static reference to an entity, and I can inspect it in the debugger for sure (so it is converted). Am I doing smth wrong? Should be exactly the same performance both the DeclareReferenced+Instantiate and SubScene ways.
     
    apkdev likes this.
  2. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    943
    This might help.
     
  3. WildMaN

    WildMaN

    Joined:
    Jan 24, 2013
    Posts:
    127
    This post describes the standard DeclareReferencedPrefabs path.

    To answer my own original question, here's the quote from Unity docs: "When you save a scene, Unity converts any Sub Scenes to a native, binary format. This format is memory-ready and can be loaded or streamed with only minimal alteration of the data in RAM. The format is ideally suited for streaming large amounts of Entities."

    So memory layout is the key difference between just storing a prefab and storing it and/or using a SubScene. Sounds like it's the best solution for prefabs containing 100k+ entities, and definitely the only feasible way for 1M+ entities.

    I've tested the following methods:
    - store actual prefab in a subscene, instantiate as usual
    - store a normal set of entities in a subscene and manually assign Prefab tag, instantiate as usual
    - store a normal set of entities in a subscene and instantiate with SceneLoadFlags.NewInstance

    First two make no difference, though the last one is blazing fast, requires some boilerplate to address the newly instantiated prefab, but unfortunately either buggy or I am missing something. Like it won't unload all copies of a subscene on sceneSystem.UnloadScene()
     
  4. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Are you saying you want to instantiate a prefab that contains 100k+ entities?

    Instantiate has not been optimized for that scale. It's been optimized for the 1-1000 entities scale and instantiating many of them.

    EntityScenes have been optimized for streaming in a large amount of entities.
     
    OndrejP likes this.
  5. WildMaN

    WildMaN

    Joined:
    Jan 24, 2013
    Posts:
    127
    Thanks for the clarification!

    And yes, I'm instantiating millions of particles. Assembling such prefabs brings the editor to its knees, but that's another problem. At least the instantiation part is clear now, hope the subscenes instantiation will help.
     
  6. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    I would instantiate particles at runtime. I would make sure that each particle is exactly one entity.
    And i would use batch instantiate on EntityManager

    EntityManager.Instantiate(Entity prefab, NativeArray<Entity> outputArray);

    This is very fast. There is even more advanced ways of doing it with tile based generation / streaming by doing the generation in a job using ExclusiveEntityTransaction and MoveEntitiesFrom.
     
    OndrejP likes this.