mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 11:00:32 +00:00
We no longer update owner variables to observers
This commit is contained in:
parent
50df4d1b1f
commit
78e8a44397
@ -25,7 +25,7 @@ public class NetworkBehaviour : MonoBehaviour
|
||||
public NetworkConnection connectionToServer { get { return myView.connectionToServer; } }
|
||||
public NetworkConnection connectionToClient { get { return myView.connectionToClient; } }
|
||||
public short playerControllerId { get { return myView.playerControllerId; } }
|
||||
protected ulong syncVarDirtyBits { get { return m_SyncVarDirtyBits; } }
|
||||
public ulong syncVarDirtyBits { get { return m_SyncVarDirtyBits; } set { m_SyncVarDirtyBits = value; } }
|
||||
protected bool syncVarHookGuard { get { return m_SyncVarGuard; } set { m_SyncVarGuard = value; }}
|
||||
// determine which variables are SyncToOwner
|
||||
// to get dirty owners, we do syncVarDirtyBits & syncVarOwnerMask
|
||||
@ -548,6 +548,11 @@ public void ClearAllDirtyBits()
|
||||
m_SyncVarDirtyBits = 0L;
|
||||
}
|
||||
|
||||
public void ClearOwnerDirtyBits()
|
||||
{
|
||||
m_SyncVarDirtyBits = m_SyncVarDirtyBits & (~syncVarOwnerMask);
|
||||
}
|
||||
|
||||
public void SetAllDirtyBits()
|
||||
{
|
||||
m_LastSendTime = float.MinValue;
|
||||
|
@ -443,9 +443,31 @@ internal bool OnSerializeSafely(NetworkBehaviour comp, NetworkWriter writer, boo
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void ClearDirtyBits(bool all= false)
|
||||
{
|
||||
foreach (NetworkBehaviour comp in m_NetworkBehaviours)
|
||||
{
|
||||
// we only want to clear the ones we just sent
|
||||
// otherwise we would be resetting the components waiting for their timer
|
||||
// waiting for their turn.
|
||||
if (comp.IsDirty() || all)
|
||||
{
|
||||
comp.ClearAllDirtyBits();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetAllDirtyBits()
|
||||
{
|
||||
foreach(NetworkBehaviour comp in m_NetworkBehaviours)
|
||||
{
|
||||
comp.SetAllDirtyBits();
|
||||
}
|
||||
}
|
||||
|
||||
// serialize all components (or only dirty ones for channelId if not initial state)
|
||||
// -> returns TRUE if any date other than dirtyMask was written!
|
||||
internal bool OnSerializeAllSafely(NetworkBehaviour[] components, NetworkWriter writer, bool initialState, int channelId)
|
||||
internal bool OnSerializeAllSafely(NetworkBehaviour[] components, NetworkWriter writer, bool initialState, SyncTarget target, int channelId)
|
||||
{
|
||||
if (components.Length > 64)
|
||||
{
|
||||
@ -462,20 +484,25 @@ internal bool OnSerializeAllSafely(NetworkBehaviour[] components, NetworkWriter
|
||||
// -> always serialize if initialState so all components with all channels are included in spawn packet
|
||||
// -> note: IsDirty() is false if the component isn't dirty or sendInterval isn't elapsed yet
|
||||
NetworkBehaviour comp = m_NetworkBehaviours[i];
|
||||
if (initialState || (comp.IsDirty() && comp.GetNetworkChannel() == channelId))
|
||||
ulong dirtyBits = comp.syncVarDirtyBits;
|
||||
|
||||
if (target == SyncTarget.Observers)
|
||||
{
|
||||
// if we are synchronizing for observers, all owner variables are treated as clean
|
||||
comp.ClearOwnerDirtyBits();
|
||||
}
|
||||
|
||||
if (comp.IsDirty() && comp.GetNetworkChannel() == channelId)
|
||||
{
|
||||
// set bit #i to 1 in dirty mask
|
||||
dirtyComponentsMask |= (ulong)(1L << i);
|
||||
|
||||
if (initialState)
|
||||
{
|
||||
comp.SetAllDirtyBits();
|
||||
}
|
||||
// serialize and clear dirty bits in any case, since the component was clearly dirty if we got here
|
||||
if (LogFilter.logDebug) { Debug.Log("OnSerializeAllSafely: " + name + " -> " + comp.GetType() + " initial=" + initialState + " channelId=" + channelId); }
|
||||
OnSerializeSafely(comp, payload, initialState);
|
||||
comp.ClearAllDirtyBits();
|
||||
}
|
||||
|
||||
// restory the dirty bits, serialization should not have side effec
|
||||
comp.syncVarDirtyBits = dirtyBits;
|
||||
}
|
||||
|
||||
// did we write anything? then write dirty, payload and return true
|
||||
@ -492,7 +519,7 @@ internal bool OnSerializeAllSafely(NetworkBehaviour[] components, NetworkWriter
|
||||
}
|
||||
|
||||
// extra version that uses m_NetworkBehaviours so we can call it from the outside
|
||||
internal void OnSerializeAllSafely(NetworkWriter writer, bool initialState, int channelId) { OnSerializeAllSafely(m_NetworkBehaviours, writer, initialState, channelId); }
|
||||
internal void OnSerializeAllSafely(NetworkWriter writer, bool initialState, SyncTarget target, int channelId) { OnSerializeAllSafely(m_NetworkBehaviours, writer, initialState, target, channelId); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -746,23 +773,78 @@ internal void UNetUpdate()
|
||||
// go through each channel
|
||||
for (int channelId = 0; channelId < NetworkServer.numChannels; channelId++)
|
||||
{
|
||||
// serialize all the dirty components and send (if any were dirty)
|
||||
NetworkWriter writer = new NetworkWriter();
|
||||
if (OnSerializeAllSafely(m_NetworkBehaviours, writer, false, channelId))
|
||||
SendUpdateVarsMessage(channelId, SyncTarget.Owner);
|
||||
SendUpdateVarsMessage(channelId, SyncTarget.Observers);
|
||||
}
|
||||
|
||||
// reset dirty bits for everything that was sent
|
||||
ClearDirtyBits();
|
||||
}
|
||||
|
||||
// sends a message to all observers except the owner
|
||||
public int SendToObservers(short msgType, MessageBase msg, int channelId)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
for (int i = 0; i < observers.Count; ++i)
|
||||
{
|
||||
NetworkConnection conn = observers[i];
|
||||
if (conn.isReady && conn != m_ClientAuthorityOwner)
|
||||
{
|
||||
if (conn.SendByChannel(msgType, msg, channelId))
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// returns true if there are no non owner observers
|
||||
public bool HasNonOwnerObserver()
|
||||
{
|
||||
return observers.Any(conn => conn != m_ClientAuthorityOwner);
|
||||
}
|
||||
|
||||
public void SendToOwner(short msgType, MessageBase msg, int channelId)
|
||||
{
|
||||
m_ClientAuthorityOwner.SendByChannel(msgType, msg, channelId);
|
||||
}
|
||||
|
||||
|
||||
private bool SendUpdateVarsMessage(int channelId, SyncTarget target)
|
||||
{
|
||||
if (m_ClientAuthorityOwner == null && target == SyncTarget.Owner)
|
||||
{
|
||||
// there is no owner
|
||||
return false;
|
||||
}
|
||||
|
||||
// serialize all the dirty components and send (if any were dirty)
|
||||
NetworkWriter writer = new NetworkWriter();
|
||||
if (OnSerializeAllSafely(m_NetworkBehaviours, writer, false, target, channelId))
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.NetworkDetailStats.IncrementStat(
|
||||
UnityEditor.NetworkDetailStats.NetworkDirection.Outgoing,
|
||||
(short)MsgType.UpdateVars, name, 1);
|
||||
#endif
|
||||
// construct message and send
|
||||
UpdateVarsMessage message = new UpdateVarsMessage();
|
||||
message.netId = netId;
|
||||
message.payload = writer.ToArray();
|
||||
// construct message and send
|
||||
UpdateVarsMessage message = new UpdateVarsMessage();
|
||||
message.netId = netId;
|
||||
message.payload = writer.ToArray();
|
||||
|
||||
NetworkServer.SendByChannelToReady(gameObject, (short)MsgType.UpdateVars, message, channelId);
|
||||
if (target == SyncTarget.Owner)
|
||||
{
|
||||
SendToOwner((short)MsgType.UpdateVars, message, channelId);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendToObservers((short)MsgType.UpdateVars, message, channelId);
|
||||
}
|
||||
|
||||
if (LogFilter.logDev) { Debug.Log("Synchronized data for " + target + ", data size = " + message.payload.Length); }
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
internal void OnUpdateVars(NetworkReader reader, bool initialState)
|
||||
@ -1076,7 +1158,6 @@ internal void Reset()
|
||||
m_NetworkBehaviours = null;
|
||||
|
||||
ClearObservers();
|
||||
m_ClientAuthorityOwner = null;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
@ -739,11 +739,18 @@ static internal bool InternalAddPlayerForConnection(NetworkConnection conn, Game
|
||||
|
||||
if (LogFilter.logDebug) { Debug.Log("Adding new playerGameObject object netId: " + playerGameObject.GetComponent<NetworkIdentity>().netId + " asset ID " + playerGameObject.GetComponent<NetworkIdentity>().assetId); }
|
||||
|
||||
FinishPlayerForConnection(conn, playerNetworkIdentity, playerGameObject);
|
||||
|
||||
// paul: Need to set owner before sending spawn message so we can avoid sending owner variables
|
||||
if (playerNetworkIdentity.localPlayerAuthority)
|
||||
{
|
||||
playerNetworkIdentity.SetClientOwner(conn);
|
||||
}
|
||||
else
|
||||
{
|
||||
playerNetworkIdentity.SetClientOwner(null);
|
||||
}
|
||||
|
||||
FinishPlayerForConnection(conn, playerNetworkIdentity, playerGameObject);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -783,11 +790,15 @@ static bool SetupLocalPlayerForConnection(NetworkConnection conn, NetworkIdentit
|
||||
uv.OnStartServer(true);
|
||||
}
|
||||
uv.RebuildObservers(true);
|
||||
|
||||
// paul: set the owner before sending the spawn message
|
||||
// so that we can avoid sending owner variables
|
||||
uv.SetClientOwner(conn);
|
||||
|
||||
SendSpawnMessage(uv, null);
|
||||
|
||||
// Set up local player instance on the client instance and update local object map
|
||||
localConnection.localClient.AddLocalPlayer(newPlayerController);
|
||||
uv.SetClientOwner(conn);
|
||||
|
||||
// Trigger OnAuthority
|
||||
uv.ForceAuthority(true);
|
||||
@ -854,11 +865,19 @@ static internal bool InternalReplacePlayerForConnection(NetworkConnection conn,
|
||||
|
||||
if (LogFilter.logDebug) { Debug.Log("Replacing playerGameObject object netId: " + playerGameObject.GetComponent<NetworkIdentity>().netId + " asset ID " + playerGameObject.GetComponent<NetworkIdentity>().assetId); }
|
||||
|
||||
FinishPlayerForConnection(conn, playerNetworkIdentity, playerGameObject);
|
||||
// paul: Need to set owner before sending spawn message so we can avoid sending owner variables
|
||||
if (playerNetworkIdentity.localPlayerAuthority)
|
||||
{
|
||||
playerNetworkIdentity.SetClientOwner(conn);
|
||||
}
|
||||
else
|
||||
{
|
||||
playerNetworkIdentity.SetClientOwner(null);
|
||||
}
|
||||
|
||||
|
||||
FinishPlayerForConnection(conn, playerNetworkIdentity, playerGameObject);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1092,69 +1111,120 @@ static internal void SendSpawnMessage(NetworkIdentity uv, NetworkConnection conn
|
||||
if (uv.serverOnly)
|
||||
return;
|
||||
|
||||
if (LogFilter.logDebug) { Debug.Log("Server SendSpawnMessage: name=" + uv.name + " sceneId=" + uv.sceneId + " netid=" + uv.netId); } // for easier debugging
|
||||
//if (LogFilter.logDebug) { Debug.Log("Server SendSpawnMessage: name=" + uv.name + " sceneId=" + uv.sceneId + " netid=" + uv.netId + " owner = " + (uv.clientAuthorityOwner != null)); } // for easier debugging
|
||||
|
||||
bool sendToOwner = uv.clientAuthorityOwner != null && (conn == null || uv.clientAuthorityOwner == conn);
|
||||
bool sendToObserver = (conn == null || uv.clientAuthorityOwner != conn);
|
||||
|
||||
int messageCount = 0;
|
||||
|
||||
// everything is dirty during spawning
|
||||
uv.SetAllDirtyBits();
|
||||
|
||||
// 'uv' is a prefab that should be spawned
|
||||
if (uv.sceneId.IsEmpty())
|
||||
{
|
||||
SpawnPrefabMessage msg = new SpawnPrefabMessage();
|
||||
msg.netId = uv.netId;
|
||||
msg.assetId = uv.assetId;
|
||||
msg.position = uv.transform.position;
|
||||
msg.rotation = uv.transform.rotation;
|
||||
|
||||
// serialize all components with initialState = true
|
||||
NetworkWriter writer = new NetworkWriter();
|
||||
uv.OnSerializeAllSafely(writer, true, -1); // channelId doesn't matter if initialState
|
||||
msg.payload = writer.ToArray();
|
||||
|
||||
// conn is != null when spawning it for a client
|
||||
if (conn != null)
|
||||
if (sendToOwner)
|
||||
{
|
||||
conn.Send((short)MsgType.SpawnPrefab, msg);
|
||||
if (LogFilter.logDebug) { Debug.Log("Server SendSpawnMessage: name=" + uv.name + " sceneId=" + uv.sceneId + " netid=" + uv.netId + " to owner=" + uv.clientAuthorityOwner.connectionId); } // for easier debugging
|
||||
messageCount += SendSpanPrefabMessage(uv, uv.clientAuthorityOwner, SyncTarget.Owner);
|
||||
}
|
||||
// conn is == null when spawning it for the local player
|
||||
else
|
||||
if (sendToObserver)
|
||||
{
|
||||
SendToReady(uv.gameObject, (short)MsgType.SpawnPrefab, msg);
|
||||
if (LogFilter.logDebug) { Debug.Log("Server SendSpawnMessage: name=" + uv.name + " sceneId=" + uv.sceneId + " netid=" + uv.netId + " to observers"); } // for easier debugging
|
||||
messageCount += SendSpanPrefabMessage(uv, conn, SyncTarget.Observers);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.NetworkDetailStats.IncrementStat(
|
||||
UnityEditor.NetworkDetailStats.NetworkDirection.Outgoing,
|
||||
(short)MsgType.SpawnPrefab, uv.assetId.ToString(), 1);
|
||||
#endif
|
||||
}
|
||||
// 'uv' is a scene object that should be spawned again
|
||||
else
|
||||
{
|
||||
SpawnSceneObjectMessage msg = new SpawnSceneObjectMessage();
|
||||
msg.netId = uv.netId;
|
||||
msg.sceneId = uv.sceneId;
|
||||
msg.position = uv.transform.position;
|
||||
|
||||
// include synch data
|
||||
NetworkWriter writer = new NetworkWriter();
|
||||
uv.OnSerializeAllSafely(writer, true, -1); // channelId doesn't matter if initialState
|
||||
msg.payload = writer.ToArray();
|
||||
|
||||
// conn is != null when spawning it for a client
|
||||
if (conn != null)
|
||||
if (sendToOwner)
|
||||
{
|
||||
conn.Send((short)MsgType.SpawnSceneObject, msg);
|
||||
if (LogFilter.logDebug) { Debug.Log("Server SendSpawnSceneObjectMessage: name=" + uv.name + " sceneId=" + uv.sceneId + " netid=" + uv.netId + " to owner=" + uv.clientAuthorityOwner.connectionId); } // for easier debugging
|
||||
messageCount += SendSpawnSceneObjectMessage(uv, uv.clientAuthorityOwner, SyncTarget.Owner);
|
||||
}
|
||||
// conn is == null when spawning it for the local player
|
||||
else
|
||||
if (sendToObserver)
|
||||
{
|
||||
SendToReady(uv.gameObject, (short)MsgType.SpawnSceneObject, msg);
|
||||
if (LogFilter.logDebug) { Debug.Log("Server SendSpawnSceneObjectMessage: name=" + uv.name + " sceneId=" + uv.sceneId + " netid=" + uv.netId + " to observers"); } // for easier debugging
|
||||
messageCount += SendSpawnSceneObjectMessage(uv, conn, SyncTarget.Observers);
|
||||
}
|
||||
}
|
||||
|
||||
// if we just spawned for everybody, clear all dirty bits
|
||||
if (messageCount >= uv.observers.Count)
|
||||
uv.ClearDirtyBits(true);
|
||||
|
||||
}
|
||||
|
||||
private static int SendSpawnSceneObjectMessage(NetworkIdentity uv, NetworkConnection conn, SyncTarget target)
|
||||
{
|
||||
SpawnSceneObjectMessage msg = new SpawnSceneObjectMessage();
|
||||
msg.netId = uv.netId;
|
||||
msg.sceneId = uv.sceneId;
|
||||
msg.position = uv.transform.position;
|
||||
|
||||
// include synch data
|
||||
NetworkWriter writer = new NetworkWriter();
|
||||
uv.OnSerializeAllSafely(writer, true, SyncTarget.Owner, -1); // channelId doesn't matter if initialState
|
||||
msg.payload = writer.ToArray();
|
||||
|
||||
int sentCount = 0;
|
||||
|
||||
// conn is != null when spawning it for a client
|
||||
if (conn != null)
|
||||
{
|
||||
if (conn.SendByChannel((short)MsgType.SpawnSceneObject, msg, Channels.DefaultReliable))
|
||||
sentCount++;
|
||||
}
|
||||
// conn is == null when spawning it for the local player
|
||||
else
|
||||
{
|
||||
sentCount += uv.SendToObservers((short)MsgType.SpawnSceneObject, msg, Channels.DefaultReliable);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.NetworkDetailStats.IncrementStat(
|
||||
UnityEditor.NetworkDetailStats.NetworkDirection.Outgoing,
|
||||
(short)MsgType.SpawnSceneObject, "sceneId", 1);
|
||||
UnityEditor.NetworkDetailStats.IncrementStat(
|
||||
UnityEditor.NetworkDetailStats.NetworkDirection.Outgoing,
|
||||
(short)MsgType.SpawnSceneObject, "sceneId", 1);
|
||||
#endif
|
||||
return sentCount;
|
||||
}
|
||||
|
||||
private static int SendSpanPrefabMessage(NetworkIdentity uv, NetworkConnection conn, SyncTarget target)
|
||||
{
|
||||
SpawnPrefabMessage msg = new SpawnPrefabMessage();
|
||||
msg.netId = uv.netId;
|
||||
msg.assetId = uv.assetId;
|
||||
msg.position = uv.transform.position;
|
||||
msg.rotation = uv.transform.rotation;
|
||||
|
||||
// serialize all components with initialState = true
|
||||
NetworkWriter writer = new NetworkWriter();
|
||||
uv.OnSerializeAllSafely(writer, true, target, -1); // channelId doesn't matter if initialState
|
||||
msg.payload = writer.ToArray();
|
||||
|
||||
int sentCount = 0;
|
||||
|
||||
// conn is != null when spawning it for a client
|
||||
if (conn != null)
|
||||
{
|
||||
if (conn.SendByChannel((short)MsgType.SpawnPrefab, msg, Channels.DefaultReliable))
|
||||
sentCount++;
|
||||
|
||||
}
|
||||
// conn is == null when spawning it for the local player
|
||||
else
|
||||
{
|
||||
sentCount+= uv.SendToObservers((short)MsgType.SpawnPrefab, msg, Channels.DefaultReliable);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.NetworkDetailStats.IncrementStat(
|
||||
UnityEditor.NetworkDetailStats.NetworkDirection.Outgoing,
|
||||
(short)MsgType.SpawnPrefab, uv.assetId.ToString(), 1);
|
||||
#endif
|
||||
|
||||
return sentCount;
|
||||
}
|
||||
|
||||
static public void DestroyPlayersForConnection(NetworkConnection conn)
|
||||
|
Loading…
Reference in New Issue
Block a user