0
\$\begingroup\$

I am building a multiplayer game server with Unity. In the game there are players moving around the map. Now, because this map is quite large compared to the number of players, I was thinking to have the server send each clients' position only when they are nearby, and then slow the rate down when they are far away.

At first I was using the convenient SyncVar to do sync everyone's position, until I discovered its shortcomings, that is there is no conditional way to either sync or not a certain value.

I came out with this player synchronization class so far (I removed all optimizations for simplicity):

public class PlayerSyncPositionConditional : NetworkBehaviour {

    Vector3 lastPos;

    void FixedUpdate () {
        TransmitPosition();
    }

    [ClientCallback]
    void TransmitPosition () {
        CmdProvidePositionToServer(transform.position);
    }

    [Command]
    void CmdProvidePositionToServer (Vector3 pos){
        transform.position = pos;
    }

}

Now, what this code does is nothing more than sending its position to the server: when I am looking at the dedicated server instance, each players' position is correct. Also, as expected, each client will not receive any updates.

From my research, I found that instead of SyncVar, I can use Server and ClientRpc to dispatch commands from the server to all clients, so this

 [Server]
 public void MoveTo() {
     RpcMoveTo(transform.position);
 }

 [ClientRPC]
 void RpcMoveTo(Vector3 newPosition) {
     transform.position = newPosition; //this will run in all clients
 }

would move all clients to the transform current position whenever needed.

Now, the problem is that those commands, apparently affect every client, while I only want to affect ones that are near each other.

I know how to have the server issue the MoveTo at any rate I want, setup more than one interval, etc. but I don't know how to have it send only to certain clients at a single time.

I am not asking for the code itself, but I am getting really confused with all these client/server architecture concepts, which class does what, etc. so any heads-up will be greatly appreciated.

\$\endgroup\$
0
\$\begingroup\$

Ok, so this is doable, but it's not very simple. For each client, you'd need to divide all other clients into your various tick rates. Then in each tick cycle, you'd send the message through per client. You can send to specific clients using commands like NetworkServer.SendToClient (2017.x)

Instead, what I'd recommend is to "chunk" your environment into various zones. Take a look at Unity's built in Sync Event(2017.x) framework. This allows each client to subscribe to updates for every zone they care about, and never receive things from zones they don't.

So if I'm in zone a, I subscribe to zone a's update event (maybe also adjacent zones' depending on how close I am to the border / how big the zone is). Someone else in zone c doesn't see my movement updates because they don't subscribe to those events until they meet certain conditions.

\$\endgroup\$
  • \$\begingroup\$ the chunk approach seems much easier and straightforward... do you know of any online resource I can have a look to get a better idea? \$\endgroup\$ – johnDoe Mar 29 '18 at 13:31
  • \$\begingroup\$ Look into spatial partitioning and find a pattern that works for you. gameprogrammingpatterns.com/spatial-partition.html here's an article that gives an overview. \$\endgroup\$ – Zebraman Mar 29 '18 at 13:46
  • \$\begingroup\$ it kind of reminds me of geohash, I have worked with it in the past already... shouldn't be too hard. what's going to be hard is subscribing, unsubscribing and sending events once inside each chuck... thanks a lot! \$\endgroup\$ – johnDoe Mar 29 '18 at 13:54
  • \$\begingroup\$ Look into using Triggers. Shouldn't be too hard to sync up various Enters and Exits with event listeners. \$\endgroup\$ – Zebraman Mar 29 '18 at 14:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.