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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question Display two worlds at the same time?

Discussion in 'Entity Component System' started by Cell-i-Zenit, Jun 14, 2020.

  1. Cell-i-Zenit

    Cell-i-Zenit

    Joined:
    Mar 11, 2016
    Posts:
    290
    Hi,

    currently my game has everything in a single world and i think i could improve code and programming a bit by restructuring the whole thing into multiple worlds.

    My game translates pretty much 1:1 with multiple worlds (eg my game has multiple parallel worlds where the player can switch to), so it would allow me to keep multiple worlds active at the same time and the player can easily switch over.

    The only problem i have is that i need to display two worlds at the same time.

    So instead of having a "presentation world" and multiple other simulation worlds, i image i would have like 10 simulation worlds, and the hybridRenderer system would be only active at two worlds.

    Is such a thing possible? How do i "overlap" the presentation of my entities? Basically i would like to merge two worlds together, but ONLY! at the presentation layer.

    Any ideas/recommentations? :)
     
    florianhanke likes this.
  2. mpforce1

    mpforce1

    Joined:
    Apr 4, 2014
    Posts:
    34
    Hi, if it helps in my project we have 2 separate worlds, 1 for the client and 1 for the server. When we create the worlds, using an ICustomBootstrap, we don't bother adding the presentation systems into the server world since the server world doesn't need to be rendered. However, for debugging it is sometimes useful to render the server world so we do add them in that case.

    Based on what you were saying you could use a bootstrap to only add the presentation systems to the worlds you want to render. Additionally, I think you can enable/disable the PresentationSystemGroup for the specific worlds you want to render/not render at any given time, that should result in the worlds rendering on top of each other. I haven't tried this so it might not work that way. I hope this helps, let me know if you need any more info :).
     
  3. Cell-i-Zenit

    Cell-i-Zenit

    Joined:
    Mar 11, 2016
    Posts:
    290
    Thanks for the answer! I think i will just try it out and see if i can have multiple active worlds with rendering. I will post the results of my tests!

    EDIT: that was a short adventure :(

    So first of all i had to fork the HybridRenderer because these lines here result in an error, since the RegisterMaterialDictionary is static and i cannot register the same type again.

    Code (CSharp):
    1. // Some hardcoded mappings to avoid dependencies to Hybrid from DOTS
    2. RegisterMaterialPropertyType<LocalToWorld>("unity_ObjectToWorld");
    3. RegisterMaterialPropertyType<WorldToLocal_Tag>("unity_WorldToObject", overrideTypeSize: 4 * 4 * 4);
    So i made it non static which allowed me to run the systems in parallel...

    and apparently they also "compute" something, but only one cube is displayed.

    Here is a github repo: https://github.com/AskMeAgain/TwoActiveWorldsTestProject

    If you press T Z or U you will enable/disable HybridRenderers of the worlds (see console for more information)

    I will look more into the hybridrenderer to see if i can enable both world rendering

    EDIT2: so i think i found the problem: in the hybridRenderer we set a global buffer and since we override it, we will onyl get one HybridRendererSystem displayed.

    Code (CSharp):
    1.  m_GPUUploader.EndAndCommit(m_ThreadedGPUUploader);
    2.                 // Bind compute buffer here globally
    3.                 // TODO: Bind it once to the shader of the batch!
    4.                 Shader.SetGlobalBuffer("unity_DOTSInstanceData", m_GPUPersistentInstanceData);
    I think the solution is to have a single "Static" system which stitches the computeBuffers together. Iam not sure if something like this is possible or not
     
    Last edited: Jun 14, 2020
  4. jdtec

    jdtec

    Joined:
    Oct 25, 2017
    Posts:
    299
    I just hit this error with the static RegisterMaterialDictionary after updating to hybrid renderer 2.

    Previously with hybrid renderer 1 I could render two worlds with no problems. I can edit the source for now I guess if I need this functionality again.
     
    PolarTron likes this.
  5. SebastianAaltonen

    SebastianAaltonen

    Unity Technologies

    Joined:
    Feb 21, 2020
    Posts:
    112
    Right now Hybrid Renderer V2 doesn't support multiple worlds. Separating the dictionary from the render system is trivial. It's only populated at the beginning and is read only from that point. No thread sync concerns.

    The bigger issue is the big compute buffer that stores all entity data for GPU. This is bound using a global binding. There's currently no mechanism to set different texture/buffer bindings for each batch, so they must all use the same big buffer. We could of course sub-allocate this buffer to multiple regions (one for each world) and then worlds could sub-allocate their own regions for their entity chunks dynamically. However this requires splitting the buffer at startup, which might be result in sub-optimal split (GPU memory is wasted).

    Once we have implemented per batch texture/buffer bindings, we have a straightforward solution for this problem. It simply works correctly automatically. No need to share any GPU data between the worlds. This feature is planned for 2021.
     
  6. PolarTron

    PolarTron

    Joined:
    Jun 21, 2013
    Posts:
    87
    I don't really need Hybrid Renderer 2 at the moment. How did you make it work with Hybrid Renderer 1?

    For context I have Default World & Client World in a multiplayer game. Entities exist in Client World, so you see the issue I'm having there as the rendering is done in Default World.
     
  7. jdtec

    jdtec

    Joined:
    Oct 25, 2017
    Posts:
    299
    I copied all entities from one world into the other on start-up. From there, as far as I remember, it just kind of worked. Although haven't used this workflow in a while as I'm back to one world for the time being & hybrid renderer 2.
     
    PolarTron likes this.
  8. PolarTron

    PolarTron

    Joined:
    Jun 21, 2013
    Posts:
    87
    DOTS into the Multiverse

    Far from optimal but sounds like a solution that could work given the current state of the packages.

    Since I'm forced to use multiple worlds (SpatialOS GDK for Unity) I'll probably treat the Client World Entities as handles and have the real entities exist in the Default World.

    I'll lose out on performance but hey, we work with what we have in preview land.

    Thanks for the reply :)
     
  9. PolarTron

    PolarTron

    Joined:
    Jun 21, 2013
    Posts:
    87
    @jdtec

    Someone showed me this. Might want to strip out systems you don't want but overall it works just fine.

    Code (CSharp):
    1. var systems = DefaultWorldInitialization.GetAllSystems(WorldSystemFilterFlags.Default);
    2. DefaultWorldInitialization.AddSystemsToRootLevelSystemGroups(World, systems);
     
    tom_i likes this.
  10. jdtec

    jdtec

    Joined:
    Oct 25, 2017
    Posts:
    299
    Yea I actually manually added the game systems I wanted to each world (filter based on namespace of the system) back when I split things across a sim and view world.

    Later on I did a prototype with time rewind/time travel (reset and playback with different inputs) stuff between multiple worlds which is where I used the copying of entities from one world to another that I previously mentioned.
     
    PolarTron likes this.