void UpdateClient() { // client authority, and local player (= allowed to move myself)? if (IsClientWithAuthority) { // send to server each 'sendInterval' // NetworkTime.localTime for double precision until Unity has it too // // IMPORTANT: // snapshot interpolation requires constant sending. // DO NOT only send if position changed. for example: // --- // * client sends first position at t=0 // * ... 10s later ... // * client moves again, sends second position at t=10 // --- // * server gets first position at t=0 // * server gets second position at t=10 // * server moves from first to second within a time of 10s // => would be a super slow move, instead of a wait & move. // // IMPORTANT: // DO NOT send nulls if not changed 'since last send' either. we // send unreliable and don't know which 'last send' the other end // received successfully. if (NetworkTime.localTime >= lastClientSendTime + sendInterval) { // send snapshot without timestamp. // receiver gets it from batch timestamp to save bandwidth. NTSnapshot snapshot = ConstructSnapshot(); CmdClientToServerSync( // only sync what the user wants to sync syncPosition ? snapshot.position : new Vector3?(), syncRotation? snapshot.rotation : new Quaternion?(), syncScale ? snapshot.scale : new Vector3?() ); lastClientSendTime = NetworkTime.localTime; } } // for all other clients (and for local player if !authority), // we need to apply snapshots from the buffer else { // compute snapshot interpolation & apply if any was spit out // TODO we don't have Time.deltaTime double yet. float is fine. if (SnapshotInterpolation.Compute( NetworkTime.localTime, Time.deltaTime, ref clientInterpolationTime, bufferTime, clientBuffer, catchupThreshold, catchupMultiplier, Interpolate, out NTSnapshot computed)) { NTSnapshot start = clientBuffer.Values[0]; NTSnapshot goal = clientBuffer.Values[1]; ApplySnapshot(start, goal, computed); } } }
// update ////////////////////////////////////////////////////////////// void UpdateServer() { // broadcast to all clients each 'sendInterval' // (client with authority will drop the rpc) // NetworkTime.localTime for double precision until Unity has it too // // IMPORTANT: // snapshot interpolation requires constant sending. // DO NOT only send if position changed. for example: // --- // * client sends first position at t=0 // * ... 10s later ... // * client moves again, sends second position at t=10 // --- // * server gets first position at t=0 // * server gets second position at t=10 // * server moves from first to second within a time of 10s // => would be a super slow move, instead of a wait & move. // // IMPORTANT: // DO NOT send nulls if not changed 'since last send' either. we // send unreliable and don't know which 'last send' the other end // received successfully. // // Checks to ensure server only sends snapshots if object is // on server authority(!clientAuthority) mode because on client // authority mode snapshots are broadcasted right after the authoritative // client updates server in the command function(see above), OR, // since host does not send anything to update the server, any client // authoritative movement done by the host will have to be broadcasted // here by checking IsClientWithAuthority. if (NetworkTime.localTime >= lastServerSendTime + sendInterval && (!clientAuthority || IsClientWithAuthority)) { // send snapshot without timestamp. // receiver gets it from batch timestamp to save bandwidth. NTSnapshot snapshot = ConstructSnapshot(); RpcServerToClientSync( // only sync what the user wants to sync syncPosition ? snapshot.position : new Vector3?(), syncRotation? snapshot.rotation : new Quaternion?(), syncScale ? snapshot.scale : new Vector3?() ); lastServerSendTime = NetworkTime.localTime; } // apply buffered snapshots IF client authority // -> in server authority, server moves the object // so no need to apply any snapshots there. // -> don't apply for host mode player objects either, even if in // client authority mode. if it doesn't go over the network, // then we don't need to do anything. if (clientAuthority && !hasAuthority) { // compute snapshot interpolation & apply if any was spit out // TODO we don't have Time.deltaTime double yet. float is fine. if (SnapshotInterpolation.Compute( NetworkTime.localTime, Time.deltaTime, ref serverInterpolationTime, bufferTime, serverBuffer, catchupThreshold, catchupMultiplier, Interpolate, out NTSnapshot computed)) { NTSnapshot start = serverBuffer.Values[0]; NTSnapshot goal = serverBuffer.Values[1]; ApplySnapshot(start, goal, computed); } } }
void UpdateClient() { // client authority, and local player (= allowed to move myself)? if (IsClientWithAuthority) { // https://github.com/vis2k/Mirror/pull/2992/ if (!NetworkClient.ready) { return; } // send to server each 'sendInterval' // NetworkTime.localTime for double precision until Unity has it too // // IMPORTANT: // snapshot interpolation requires constant sending. // DO NOT only send if position changed. for example: // --- // * client sends first position at t=0 // * ... 10s later ... // * client moves again, sends second position at t=10 // --- // * server gets first position at t=0 // * server gets second position at t=10 // * server moves from first to second within a time of 10s // => would be a super slow move, instead of a wait & move. // // IMPORTANT: // DO NOT send nulls if not changed 'since last send' either. we // send unreliable and don't know which 'last send' the other end // received successfully. if (NetworkTime.localTime >= lastClientSendTime + sendInterval) { // send snapshot without timestamp. // receiver gets it from batch timestamp to save bandwidth. NTSnapshot snapshot = ConstructSnapshot(); #if onlySyncOnChange_BANDWIDTH_SAVING cachedSnapshotComparison = CompareSnapshots(snapshot); if (cachedSnapshotComparison && hasSentUnchangedPosition && onlySyncOnChange) { return; } #endif #if onlySyncOnChange_BANDWIDTH_SAVING CmdClientToServerSync( // only sync what the user wants to sync syncPosition && positionChanged ? snapshot.position : default(Vector3?), syncRotation && rotationChanged ? snapshot.rotation : default(Quaternion?), syncScale && scaleChanged ? snapshot.scale : default(Vector3?) ); #else CmdClientToServerSync( // only sync what the user wants to sync syncPosition ? snapshot.position : default(Vector3?), syncRotation ? snapshot.rotation : default(Quaternion?), syncScale ? snapshot.scale : default(Vector3?) ); #endif lastClientSendTime = NetworkTime.localTime; #if onlySyncOnChange_BANDWIDTH_SAVING if (cachedSnapshotComparison) { hasSentUnchangedPosition = true; } else { hasSentUnchangedPosition = false; lastSnapshot = snapshot; } #endif } } // for all other clients (and for local player if !authority), // we need to apply snapshots from the buffer else { // compute snapshot interpolation & apply if any was spit out // TODO we don't have Time.deltaTime double yet. float is fine. if (SnapshotInterpolation.Compute( NetworkTime.localTime, Time.deltaTime, ref clientInterpolationTime, bufferTime, clientBuffer, catchupThreshold, catchupMultiplier, Interpolate, out NTSnapshot computed)) { NTSnapshot start = clientBuffer.Values[0]; NTSnapshot goal = clientBuffer.Values[1]; ApplySnapshot(start, goal, computed); } } }