Hi,
I am creating a game where different players can build a home together. A home may consist of thousands of objects (blocks, furniture, etc). What comes to my mind is to add a CoherenceSync component to each object. However, this will lead to having thousands of CoherenceSync components in the scene. Is that a good practice or is there another way?
You can imagine my game as if it was a minecraft world where players can build stuff together. Note that, most of the gameobjects will never change their position once they are placed.
At this scale, my recommendation would be to send this static information as the data changes, not with real-time sync. Meaning, don’t use CoherenceSync on them, but instead use commands to send state changes to the data and have the clients manage the static object placement. Messaging with Commands | Unity Multiplayer SDK Documentation | coherence
CoherenceSync is great for real-time changes in properties being synced, but if your objects don’t change after initialization then there is overhead in having thousands of them in your scene. This recommendation would be different at a smaller scale where you could go ahead and just make the CoherenceSync objects.
One option if your objects are mostly idle but may be interacted with during gameplay is to replace them on-the-fly with CoherenceSynced versions when they are interacted with.
To get a better idea on how to proceed, I will split my question into multiple questions:
- Are you suggesting using commands because adding CoherenceSync to all objects is a “bad” idea or is it just unnecessary? In other words, does it severly increase the lag? Because I heard that as long as the variables values are not changing (which is the case here), CoherenceSync will not sync the values (so there will be no lag).
- By “using commands”, you mean that once the object is going to be placed, a command is sent to all players to “Place the object” in their scenes? But isnt there a possibility that the command fails to reach some of the users?
- Suppose a player joined a room where the players are in the middle of building a home. How would the player “download” the current home (list of placed objects) using Commands?
- You are correct that if the variables don’t change we don’t send anything over the wire for these entities, but for each entity that has coherence sync a calculation must be made to diff any fields (at the very least position). This can add up. There’s also a 1000 entity limit per room if you’re using coherence Cloud Configure Rooms | Unity Multiplayer SDK Documentation | coherence
2 & 3. The approach I’d use given what I understand of your use case is that either the authoritative client (e.g. a sim) or every client keeps something like a List<Vector3>
of where these items are placed. When one is added or removed a corresponding command is sent. I believe this has the same delivery guarantee as e.g. instantiating a network entity once that never changes, but let me check with the engine and SDK team on this.
A client that is joining a room in progress can request from another client the full List of placements via series of commands that serialize the list into chunks.
We realize this is a bit cumbersome at the moment. Our SDK to date has prioritized real-time sync of primitive fields, but we know your scenario and many others like it are a common request from all of our customers. It’s one of our top priorities figuring out how we can fit things like easy List sync and large data sync into our SDK - I don’t have an exact date or timeline but we plan to add support for this in some capacity in the near future.
Please let me know what the SDK team say about the delivery guarantee of the commands.
About “syncing/downloading large data”, since its a separate question, I wrote it here: Mimicking "Request" and "Response" in Coherence
Thanks for making a separate post on the longer question. Regarding commands, the engine team has to say:
commands are reliable EXCEPT:
- if someone connects after the command is sent (unlike state, the command isn’t saved) (this is in their nature and something you have pointed out vs state replication)
- if an entity is in the middle of authority transfer, there are opportunities for the command to be lost because it’s a complex problem we don’t have a perfect solution for.
About the 1000 entity limit per room, what happens if it was exceeded? Will the 1000 nearest objects be synced?
Also, do entities outside the livequery count?
From the engine team:
that count is entities in the system total across all clients in the room. Extra entities are rejected and deleted with a warning on the RS.
@codya this may be a little late, but I recommend not using Coherence for this specific scenario. I.e. keep using Coherence for everything else in your game, but this is a special case, and I would use a different strategy.
When I’ve faced similar issues on network systems, I would keep a permanent state server separate from a sync server. Coherence is really good for keeping states synced between active objects in a game, but you are describing a permanent change to the world.
My solution would be to update a web service that I have placed an object in the world. A wall or roof or door, etc. I would also add the object as a network object in coherence temporarily. This way anyone else in the area sees it. However, after my web service update is complete, I would delete the sync object, and send a message out similar to “RefreshArea(coordinates to area)” (your custom message) All other players in that area should receive it. And then call up the API for permanant state, and deal with any changes, such as the new wall put up by another user.
As new users come into the area, they should automatically be asking for updates to the area.
I’m not aware if Coherence provides anything like that, but I would check there first, and then look at creating a separate service or some form of JSON db service to manage this. I.e. Just because Coherence provides networking doesn’t mean you should try to stuff every network need into their service, and I think this is a great candidate to move outside.
Thanks, this is what I decided to do too. An HTTP server that users can query occasionally to download all the new updates.