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

Question What is the best way to do full rendering isolation by scene?

Discussion in 'Multiplayer Dev Blitz Day 2023 - Q&A' started by Yoraiz0r, Jul 20, 2023.

  1. Yoraiz0r

    Yoraiz0r

    Joined:
    Apr 26, 2015
    Posts:
    60
    When you have a multiplayer game, there is often a desire for separated instances of scenes / worlds, which run for different players.

    For example, imagine the same "dungeon map" but there are two teams of four players, each going through it.
    Rather than spinning up and running separate servers for them, I'd like to have those same maps in the same game instance.

    I'm aware that you can create observer groups to each party of players, such that the relevant entities / gameobjects will only show for one group and not another. This will allow different players to see different enemies, puzzle pieces, etc... but this has a few caveats
    • Everything has to be given observer groups, in case the scenes are not identical. The server has to have both scenes loaded at the same time, but each player would only be able to see one scene. Messing with the 'active' scene also seems problematic if different clients expect it to be a different one. I also considered making rooms be prefabs, but then there's loss to ease of authoring a level (since you can't just load it in the editor, you have to start doing everything from prefab context, and having networked entities in the scene is a whole other fiasco)
    • Every dynamically spawned object has to be given its relevant observer group every time.
    • The server has further work in that it has to isolate the physics scenes of each object even if the client has requested their creation. Otherwise different room's contents would interact with each other. In addition, it also complicates all the physics casts on the server.
    In the past I've looked into the idea of scene rendering isolation, I also saw that the Unity default Camera component has a "scene" field... but that it only accepts previewscenes, to my incredible disappointment. Further, audio has no way to be isolated at all short of having a script control the volume of each audio player manually.

    When DOTS entered first previews, I was extremely excited for its ability to have isolated worlds, for the prospect of having multiple client instances at once with easy toggling. However, it seems that there is no way to disable the presentation system group of a world safely (all entities stay visible, they just never update their positions until the system group is enabled). It's a real bummer as it could have enabled multiple client tests at the same time on the same unity player instance. It's been requested since 2020 as far as I can tell on the forums, but the note remained for years that Entities Graphics does not support multiple worlds, and has not been updated.

    With all of the above, I'd like to ask what is the best way to do full isolation (physics, audio, visuals) by scene in the context of multiplayer please?
     
    JesOb likes this.
  2. NoelStephens_Unity

    NoelStephens_Unity

    Unity Technologies

    Joined:
    Feb 12, 2022
    Posts:
    48
    I have sat and pondered this question a bit and originally had a bunch of text written...then realized I needed to ask a question first:(...so I deleted all of that text... (been bouncing back and fourth between this particular question and several others).

    So, to make sure I understand... you want a single server that can host multiple unique game session of the same map(s)/scene(s) but isolate each instance of the duplicated map(s)/scene(s) so they are unique to each network session instance...or in other words...host more than one network session on the same server?

    (If so I have an answer that you partially covered but want to make sure I am understanding your question correctly)
     
    Yoraiz0r and JesOb like this.
  3. Yoraiz0r

    Yoraiz0r

    Joined:
    Apr 26, 2015
    Posts:
    60
    I'm not sure if that last part about being unique to network session instances is accurate, but that's something I would love to read as well!

    I meant that within the same connection I'd like to be able to cull out what is seen to whom, per player, without creating oddities. I find these situations come up a lot in bigger games, for example...
    • Players in a networked game run "solo" dungeons at the same time / as a race to see who can emerge victorious first. (imagine as though you had the same corridor scene for each player, at the same time, without their run contents interfering with each other
    • Menus, and dungeons and personal houses in games players can enter, whilst other players remain in their original scenes, without being removed from the connection (Bob's going to Character Creation Scene doesn't interrupt Alice's attempts to explore the game's map world)
    • Actual "cutscene" scenes, where you stop seeing some entities that are otherwise playing - just fine for everyone else in the room you are watching the cutscene of, without ever breaking synchronization. (e.g. party of 4 players are in a room ,but player2 opens a letter that prompts a quest cutscene for them with a long dialogue. the other players see none of it, no weird collisions for them to report etc.
    Basically - keep the connection, separate the objects into different buckets only some of which are visible to every user, with at most ease as possible. Apologies if I'm not descriptive enough.

    I want to know how you'd recommend to approach those cases, please!
     
  4. CMarastoni

    CMarastoni

    Unity Technologies

    Joined:
    Mar 18, 2020
    Posts:
    774
    You can have presentation toggling for 1.0 but requires some changes in the Entity.Graphics package. I achieved that in hackday of mine, with good results. I could even have multiple clients rendere in different viewport at the same time.

    Depending on the use case, you can also have multiple worlds with different servers, but that would complicate logic quite a bit at the moment.
    So keeping one server and multiple scenes loaded is definitively simpler (but less elegant in a way).

    For scene separation in itself it is just a matter of using sub-scene and organise them in a certain way.
    All sub-scenes must have auto-load set to false so you control what to load.

    In order to allow the client to load only what needed, you need to have as a requirement (for making things a little possible) one sub-scenes with all the ghost prefab. This is loaded by server a clients. The reason for this is due to the fact clients need to know all the prefabs used by the server. This just simplify some things.

    Then you can have N level scenes, whatever you want. Server load all of them, or what need to load and simulate what need to simulate.
    Clients load only the sub-scene relevant to them, when the server tell them to do so or based on other logic, There is 0 problem, it is up to you to decide how to orchestrate scene loading. It is flexible.

    The key part then is relevancy on the Server need to use relevancy and and include for each client only entities for scene X.
    Each entity already have a SceneTag (shared component) that is set to the sub-scene from which the prefab is loaded. In your game spawning system if you change that tag to match the scene for which it should belong, the relevancy became as simple as as query using a SharedComponentFilter.
    Of course this requires some custom spawning logic. But it is achievable.
    You may also consider to have a specialise shared component too (up to you). Scene data, in particular physics stuff, must be kept physically separated (or you need some custom handling or using multiple physics worlds, but this can be a little complex topic in this case).
     
    Yoraiz0r likes this.