mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 11:00:32 +00:00
refactor: Simplify spawn message (#1195)
* refactor: Simplify spawn message * Update Assets/Mirror/Runtime/Messages.cs * fix brainfart * consolidate spawning logic * simpler find * remove unnecesary private keyword * Remove redundant else
This commit is contained in:
parent
6765da2387
commit
f70a2ac702
@ -438,28 +438,32 @@ public static GameObject FindLocalObject(uint netId)
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ApplySpawnPayload(NetworkIdentity identity, Vector3 position, Quaternion rotation, Vector3 scale, ArraySegment<byte> payload, uint netId)
|
static void ApplySpawnPayload(NetworkIdentity identity, SpawnMessage msg)
|
||||||
{
|
{
|
||||||
|
identity.Reset();
|
||||||
|
identity.pendingLocalPlayer = msg.isLocalPlayer;
|
||||||
|
identity.assetId = msg.assetId;
|
||||||
|
|
||||||
if (!identity.gameObject.activeSelf)
|
if (!identity.gameObject.activeSelf)
|
||||||
{
|
{
|
||||||
identity.gameObject.SetActive(true);
|
identity.gameObject.SetActive(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply local values for VR support
|
// apply local values for VR support
|
||||||
identity.transform.localPosition = position;
|
identity.transform.localPosition = msg.position;
|
||||||
identity.transform.localRotation = rotation;
|
identity.transform.localRotation = msg.rotation;
|
||||||
identity.transform.localScale = scale;
|
identity.transform.localScale = msg.scale;
|
||||||
|
|
||||||
// deserialize components if any payload
|
// deserialize components if any payload
|
||||||
// (Count is 0 if there were no components)
|
// (Count is 0 if there were no components)
|
||||||
if (payload.Count > 0)
|
if (msg.payload.Count > 0)
|
||||||
{
|
{
|
||||||
NetworkReader payloadReader = new NetworkReader(payload);
|
NetworkReader payloadReader = new NetworkReader(msg.payload);
|
||||||
identity.OnUpdateVars(payloadReader, true);
|
identity.OnUpdateVars(payloadReader, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
identity.netId = netId;
|
identity.netId = msg.netId;
|
||||||
NetworkIdentity.spawned[netId] = identity;
|
NetworkIdentity.spawned[msg.netId] = identity;
|
||||||
|
|
||||||
// objects spawned as part of initial state are started on a second pass
|
// objects spawned as part of initial state are started on a second pass
|
||||||
if (isSpawnFinished)
|
if (isSpawnFinished)
|
||||||
@ -469,14 +473,14 @@ static void ApplySpawnPayload(NetworkIdentity identity, Vector3 position, Quater
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void OnSpawnPrefab(NetworkConnection _, SpawnPrefabMessage msg)
|
internal static void OnSpawn(NetworkConnection _, SpawnMessage msg)
|
||||||
{
|
{
|
||||||
if (msg.assetId == Guid.Empty)
|
if (msg.assetId == Guid.Empty && msg.sceneId == 0)
|
||||||
{
|
{
|
||||||
Debug.LogError("OnObjSpawn netId: " + msg.netId + " has invalid asset Id");
|
Debug.LogError("OnObjSpawn netId: " + msg.netId + " has invalid asset Id");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (LogFilter.Debug) Debug.Log("Client spawn handler instantiating [netId:" + msg.netId + " asset ID:" + msg.assetId + " pos:" + msg.position + "]");
|
if (LogFilter.Debug) Debug.Log($"Client spawn handler instantiating netId={msg.netId} assetID={msg.assetId} sceneId={msg.sceneId} pos={msg.position}");
|
||||||
|
|
||||||
// is this supposed to be the local player?
|
// is this supposed to be the local player?
|
||||||
if (msg.isLocalPlayer)
|
if (msg.isLocalPlayer)
|
||||||
@ -484,14 +488,31 @@ internal static void OnSpawnPrefab(NetworkConnection _, SpawnPrefabMessage msg)
|
|||||||
OnSpawnMessageForLocalPlayer(msg.netId);
|
OnSpawnMessageForLocalPlayer(msg.netId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity localObject) && localObject != null)
|
// was the object already spawned?
|
||||||
|
NetworkIdentity identity = GetExistingObject(msg.netId);
|
||||||
|
|
||||||
|
if (identity == null)
|
||||||
{
|
{
|
||||||
// this object already exists (was in the scene), just apply the update to existing object
|
identity = msg.sceneId == 0 ? SpawnPrefab(msg) : SpawnSceneObject(msg);
|
||||||
localObject.Reset();
|
}
|
||||||
ApplySpawnPayload(localObject, msg.position, msg.rotation, msg.scale, msg.payload, msg.netId);
|
|
||||||
|
if (identity == null)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Could not spawn assetId={msg.assetId} scene={msg.sceneId} netId={msg.netId}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ApplySpawnPayload(identity, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static NetworkIdentity GetExistingObject(uint netid)
|
||||||
|
{
|
||||||
|
NetworkIdentity.spawned.TryGetValue(netid, out NetworkIdentity localObject);
|
||||||
|
return localObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NetworkIdentity SpawnPrefab(SpawnMessage msg)
|
||||||
|
{
|
||||||
if (GetPrefab(msg.assetId, out GameObject prefab))
|
if (GetPrefab(msg.assetId, out GameObject prefab))
|
||||||
{
|
{
|
||||||
GameObject obj = Object.Instantiate(prefab, msg.position, msg.rotation);
|
GameObject obj = Object.Instantiate(prefab, msg.position, msg.rotation);
|
||||||
@ -500,60 +521,24 @@ internal static void OnSpawnPrefab(NetworkConnection _, SpawnPrefabMessage msg)
|
|||||||
Debug.Log("Client spawn handler instantiating [netId:" + msg.netId + " asset ID:" + msg.assetId + " pos:" + msg.position + " rotation: " + msg.rotation + "]");
|
Debug.Log("Client spawn handler instantiating [netId:" + msg.netId + " asset ID:" + msg.assetId + " pos:" + msg.position + " rotation: " + msg.rotation + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
localObject = obj.GetComponent<NetworkIdentity>();
|
return obj.GetComponent<NetworkIdentity>();
|
||||||
if (localObject == null)
|
|
||||||
{
|
|
||||||
Debug.LogError("Client object spawned for " + msg.assetId + " does not have a NetworkIdentity");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
localObject.Reset();
|
|
||||||
localObject.pendingLocalPlayer = msg.isLocalPlayer;
|
|
||||||
ApplySpawnPayload(localObject, msg.position, msg.rotation, msg.scale, msg.payload, msg.netId);
|
|
||||||
}
|
}
|
||||||
// lookup registered factory for type:
|
if (spawnHandlers.TryGetValue(msg.assetId, out SpawnDelegate handler))
|
||||||
else if (spawnHandlers.TryGetValue(msg.assetId, out SpawnDelegate handler))
|
|
||||||
{
|
{
|
||||||
GameObject obj = handler(msg.position, msg.assetId);
|
GameObject obj = handler(msg.position, msg.assetId);
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("Client spawn handler for " + msg.assetId + " returned null");
|
Debug.LogWarning("Client spawn handler for " + msg.assetId + " returned null");
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
localObject = obj.GetComponent<NetworkIdentity>();
|
return obj.GetComponent<NetworkIdentity>();
|
||||||
if (localObject == null)
|
|
||||||
{
|
|
||||||
Debug.LogError("Client object spawned for " + msg.assetId + " does not have a network identity");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
localObject.Reset();
|
|
||||||
localObject.pendingLocalPlayer = msg.isLocalPlayer;
|
|
||||||
localObject.assetId = msg.assetId;
|
|
||||||
ApplySpawnPayload(localObject, msg.position, msg.rotation, msg.scale, msg.payload, msg.netId);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.LogError("Failed to spawn server object, did you forget to add it to the NetworkManager? assetId=" + msg.assetId + " netId=" + msg.netId);
|
|
||||||
}
|
}
|
||||||
|
Debug.LogError("Failed to spawn server object, did you forget to add it to the NetworkManager? assetId=" + msg.assetId + " netId=" + msg.netId);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void OnSpawnSceneObject(NetworkConnection _, SpawnSceneObjectMessage msg)
|
static NetworkIdentity SpawnSceneObject(SpawnMessage msg)
|
||||||
{
|
{
|
||||||
if (LogFilter.Debug) Debug.Log("Client spawn scene handler instantiating [netId:" + msg.netId + " sceneId:" + msg.sceneId + " pos:" + msg.position);
|
|
||||||
|
|
||||||
// is this supposed to be the local player?
|
|
||||||
if (msg.isLocalPlayer)
|
|
||||||
{
|
|
||||||
OnSpawnMessageForLocalPlayer(msg.netId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity localObject) && localObject != null)
|
|
||||||
{
|
|
||||||
// this object already exists (was in the scene)
|
|
||||||
localObject.Reset();
|
|
||||||
ApplySpawnPayload(localObject, msg.position, msg.rotation, msg.scale, msg.payload, msg.netId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NetworkIdentity spawnedId = SpawnSceneObject(msg.sceneId);
|
NetworkIdentity spawnedId = SpawnSceneObject(msg.sceneId);
|
||||||
if (spawnedId == null)
|
if (spawnedId == null)
|
||||||
{
|
{
|
||||||
@ -565,14 +550,10 @@ internal static void OnSpawnSceneObject(NetworkConnection _, SpawnSceneObjectMes
|
|||||||
foreach (KeyValuePair<ulong, NetworkIdentity> kvp in spawnableObjects)
|
foreach (KeyValuePair<ulong, NetworkIdentity> kvp in spawnableObjects)
|
||||||
Debug.Log("Spawnable: SceneId=" + kvp.Key + " name=" + kvp.Value.name);
|
Debug.Log("Spawnable: SceneId=" + kvp.Key + " name=" + kvp.Value.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LogFilter.Debug) Debug.Log("Client spawn for [netId:" + msg.netId + "] [sceneId:" + msg.sceneId + "] obj:" + spawnedId.gameObject.name);
|
if (LogFilter.Debug) Debug.Log("Client spawn for [netId:" + msg.netId + "] [sceneId:" + msg.sceneId + "] obj:" + spawnedId.gameObject.name);
|
||||||
spawnedId.Reset();
|
return spawnedId;
|
||||||
spawnedId.pendingLocalPlayer = msg.isLocalPlayer;
|
|
||||||
ApplySpawnPayload(spawnedId, msg.position, msg.rotation, msg.scale, msg.payload, msg.netId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void OnObjectSpawnStarted(NetworkConnection _, ObjectSpawnStartedMessage msg)
|
internal static void OnObjectSpawnStarted(NetworkConnection _, ObjectSpawnStartedMessage msg)
|
||||||
@ -659,15 +640,7 @@ internal static void OnLocalClientObjectHide(NetworkConnection _, ObjectHideMess
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void OnLocalClientSpawnPrefab(NetworkConnection _, SpawnPrefabMessage msg)
|
internal static void OnLocalClientSpawn(NetworkConnection _, SpawnMessage msg)
|
||||||
{
|
|
||||||
if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity localObject) && localObject != null)
|
|
||||||
{
|
|
||||||
localObject.OnSetLocalVisibility(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void OnLocalClientSpawnSceneObject(NetworkConnection _, SpawnSceneObjectMessage msg)
|
|
||||||
{
|
{
|
||||||
if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity localObject) && localObject != null)
|
if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity localObject) && localObject != null)
|
||||||
{
|
{
|
||||||
|
@ -312,10 +312,11 @@ public void Serialize(NetworkWriter writer)
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal System Messages
|
#region Internal System Messages
|
||||||
public struct SpawnPrefabMessage : IMessageBase
|
public struct SpawnMessage : IMessageBase
|
||||||
{
|
{
|
||||||
public uint netId;
|
public uint netId;
|
||||||
public bool isLocalPlayer;
|
public bool isLocalPlayer;
|
||||||
|
public ulong sceneId;
|
||||||
public Guid assetId;
|
public Guid assetId;
|
||||||
public Vector3 position;
|
public Vector3 position;
|
||||||
public Quaternion rotation;
|
public Quaternion rotation;
|
||||||
@ -328,7 +329,11 @@ public void Deserialize(NetworkReader reader)
|
|||||||
{
|
{
|
||||||
netId = reader.ReadPackedUInt32();
|
netId = reader.ReadPackedUInt32();
|
||||||
isLocalPlayer = reader.ReadBoolean();
|
isLocalPlayer = reader.ReadBoolean();
|
||||||
assetId = reader.ReadGuid();
|
sceneId = reader.ReadPackedUInt64();
|
||||||
|
if (sceneId == 0)
|
||||||
|
{
|
||||||
|
assetId = reader.ReadGuid();
|
||||||
|
}
|
||||||
position = reader.ReadVector3();
|
position = reader.ReadVector3();
|
||||||
rotation = reader.ReadQuaternion();
|
rotation = reader.ReadQuaternion();
|
||||||
scale = reader.ReadVector3();
|
scale = reader.ReadVector3();
|
||||||
@ -339,42 +344,11 @@ public void Serialize(NetworkWriter writer)
|
|||||||
{
|
{
|
||||||
writer.WritePackedUInt32(netId);
|
writer.WritePackedUInt32(netId);
|
||||||
writer.WriteBoolean(isLocalPlayer);
|
writer.WriteBoolean(isLocalPlayer);
|
||||||
writer.WriteGuid(assetId);
|
writer.WritePackedUInt64(sceneId);
|
||||||
writer.WriteVector3(position);
|
if (sceneId == 0)
|
||||||
writer.WriteQuaternion(rotation);
|
{
|
||||||
writer.WriteVector3(scale);
|
writer.WriteGuid(assetId);
|
||||||
writer.WriteBytesAndSizeSegment(payload);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct SpawnSceneObjectMessage : IMessageBase
|
|
||||||
{
|
|
||||||
public uint netId;
|
|
||||||
public bool isLocalPlayer;
|
|
||||||
public ulong sceneId;
|
|
||||||
public Vector3 position;
|
|
||||||
public Quaternion rotation;
|
|
||||||
public Vector3 scale;
|
|
||||||
// the serialized component data
|
|
||||||
// -> ArraySegment to avoid unnecessary allocations
|
|
||||||
public ArraySegment<byte> payload;
|
|
||||||
|
|
||||||
public void Deserialize(NetworkReader reader)
|
|
||||||
{
|
|
||||||
netId = reader.ReadPackedUInt32();
|
|
||||||
isLocalPlayer = reader.ReadBoolean();
|
|
||||||
sceneId = reader.ReadUInt64();
|
|
||||||
position = reader.ReadVector3();
|
|
||||||
rotation = reader.ReadQuaternion();
|
|
||||||
scale = reader.ReadVector3();
|
|
||||||
payload = reader.ReadBytesAndSizeSegment();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Serialize(NetworkWriter writer)
|
|
||||||
{
|
|
||||||
writer.WritePackedUInt32(netId);
|
|
||||||
writer.WriteBoolean(isLocalPlayer);
|
|
||||||
writer.WriteUInt64(sceneId);
|
|
||||||
writer.WriteVector3(position);
|
writer.WriteVector3(position);
|
||||||
writer.WriteQuaternion(rotation);
|
writer.WriteQuaternion(rotation);
|
||||||
writer.WriteVector3(scale);
|
writer.WriteVector3(scale);
|
||||||
|
@ -344,8 +344,7 @@ internal static void RegisterSystemHandlers(bool localClient)
|
|||||||
RegisterHandler<ObjectDestroyMessage>(ClientScene.OnLocalClientObjectDestroy);
|
RegisterHandler<ObjectDestroyMessage>(ClientScene.OnLocalClientObjectDestroy);
|
||||||
RegisterHandler<ObjectHideMessage>(ClientScene.OnLocalClientObjectHide);
|
RegisterHandler<ObjectHideMessage>(ClientScene.OnLocalClientObjectHide);
|
||||||
RegisterHandler<NetworkPongMessage>((conn, msg) => { }, false);
|
RegisterHandler<NetworkPongMessage>((conn, msg) => { }, false);
|
||||||
RegisterHandler<SpawnPrefabMessage>(ClientScene.OnLocalClientSpawnPrefab);
|
RegisterHandler<SpawnMessage>(ClientScene.OnLocalClientSpawn);
|
||||||
RegisterHandler<SpawnSceneObjectMessage>(ClientScene.OnLocalClientSpawnSceneObject);
|
|
||||||
RegisterHandler<ObjectSpawnStartedMessage>((conn, msg) => { }); // host mode doesn't need spawning
|
RegisterHandler<ObjectSpawnStartedMessage>((conn, msg) => { }); // host mode doesn't need spawning
|
||||||
RegisterHandler<ObjectSpawnFinishedMessage>((conn, msg) => { }); // host mode doesn't need spawning
|
RegisterHandler<ObjectSpawnFinishedMessage>((conn, msg) => { }); // host mode doesn't need spawning
|
||||||
RegisterHandler<UpdateVarsMessage>((conn, msg) => { });
|
RegisterHandler<UpdateVarsMessage>((conn, msg) => { });
|
||||||
@ -355,8 +354,7 @@ internal static void RegisterSystemHandlers(bool localClient)
|
|||||||
RegisterHandler<ObjectDestroyMessage>(ClientScene.OnObjectDestroy);
|
RegisterHandler<ObjectDestroyMessage>(ClientScene.OnObjectDestroy);
|
||||||
RegisterHandler<ObjectHideMessage>(ClientScene.OnObjectHide);
|
RegisterHandler<ObjectHideMessage>(ClientScene.OnObjectHide);
|
||||||
RegisterHandler<NetworkPongMessage>(NetworkTime.OnClientPong, false);
|
RegisterHandler<NetworkPongMessage>(NetworkTime.OnClientPong, false);
|
||||||
RegisterHandler<SpawnPrefabMessage>(ClientScene.OnSpawnPrefab);
|
RegisterHandler<SpawnMessage>(ClientScene.OnSpawn);
|
||||||
RegisterHandler<SpawnSceneObjectMessage>(ClientScene.OnSpawnSceneObject);
|
|
||||||
RegisterHandler<ObjectSpawnStartedMessage>(ClientScene.OnObjectSpawnStarted);
|
RegisterHandler<ObjectSpawnStartedMessage>(ClientScene.OnObjectSpawnStarted);
|
||||||
RegisterHandler<ObjectSpawnFinishedMessage>(ClientScene.OnObjectSpawnFinished);
|
RegisterHandler<ObjectSpawnFinishedMessage>(ClientScene.OnObjectSpawnFinished);
|
||||||
RegisterHandler<UpdateVarsMessage>(ClientScene.OnUpdateVarsMessage);
|
RegisterHandler<UpdateVarsMessage>(ClientScene.OnUpdateVarsMessage);
|
||||||
|
@ -1077,7 +1077,7 @@ internal static void SendSpawnMessage(NetworkIdentity identity, NetworkConnectio
|
|||||||
// 'identity' is a prefab that should be spawned
|
// 'identity' is a prefab that should be spawned
|
||||||
if (identity.sceneId == 0)
|
if (identity.sceneId == 0)
|
||||||
{
|
{
|
||||||
SpawnPrefabMessage msg = new SpawnPrefabMessage
|
SpawnMessage msg = new SpawnMessage
|
||||||
{
|
{
|
||||||
netId = identity.netId,
|
netId = identity.netId,
|
||||||
isLocalPlayer = conn?.identity == identity,
|
isLocalPlayer = conn?.identity == identity,
|
||||||
@ -1119,7 +1119,7 @@ internal static void SendSpawnMessage(NetworkIdentity identity, NetworkConnectio
|
|||||||
// 'identity' is a scene object that should be spawned again
|
// 'identity' is a scene object that should be spawned again
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SpawnSceneObjectMessage msg = new SpawnSceneObjectMessage
|
SpawnMessage msg = new SpawnMessage
|
||||||
{
|
{
|
||||||
netId = identity.netId,
|
netId = identity.netId,
|
||||||
isLocalPlayer = conn?.identity == identity,
|
isLocalPlayer = conn?.identity == identity,
|
||||||
|
Loading…
Reference in New Issue
Block a user