fix: #2705 NetworkClient.SpawnPrefab looks for spawn handlers before looking for registered prefabs, instead of the other way around

This commit is contained in:
vis2k 2022-04-04 19:07:11 +08:00
parent 7d4a9c46e4
commit eded0a2b15
2 changed files with 21 additions and 12 deletions

View File

@ -1078,12 +1078,13 @@ static NetworkIdentity GetExistingObject(uint netid)
static NetworkIdentity SpawnPrefab(SpawnMessage message) static NetworkIdentity SpawnPrefab(SpawnMessage message)
{ {
if (GetPrefab(message.assetId, out GameObject prefab)) // custom spawn handler for this prefab? (for prefab pools etc.)
{ //
GameObject obj = GameObject.Instantiate(prefab, message.position, message.rotation); // IMPORTANT: look for spawn handlers BEFORE looking for registered
//Debug.Log($"Client spawn handler instantiating [netId{message.netId} asset ID:{message.assetId} pos:{message.position} rotation:{message.rotation}]"); // prefabs. Unspawning also looks for unspawn handlers
return obj.GetComponent<NetworkIdentity>(); // before falling back to regular Destroy. this needs to
} // be consistent.
// https://github.com/vis2k/Mirror/issues/2705
if (spawnHandlers.TryGetValue(message.assetId, out SpawnHandlerDelegate handler)) if (spawnHandlers.TryGetValue(message.assetId, out SpawnHandlerDelegate handler))
{ {
GameObject obj = handler(message); GameObject obj = handler(message);
@ -1100,6 +1101,15 @@ static NetworkIdentity SpawnPrefab(SpawnMessage message)
} }
return identity; return identity;
} }
// otherwise look in NetworkManager registered prefabs
if (GetPrefab(message.assetId, out GameObject prefab))
{
GameObject obj = GameObject.Instantiate(prefab, message.position, message.rotation);
//Debug.Log($"Client spawn handler instantiating [netId{message.netId} asset ID:{message.assetId} pos:{message.position} rotation:{message.rotation}]");
return obj.GetComponent<NetworkIdentity>();
}
Debug.LogError($"Failed to spawn server object, did you forget to add it to the NetworkManager? assetId={message.assetId} netId={message.netId}"); Debug.LogError($"Failed to spawn server object, did you forget to add it to the NetworkManager? assetId={message.assetId} netId={message.netId}");
return null; return null;
} }
@ -1348,13 +1358,13 @@ static void DestroyObject(uint netId)
localObject.OnStopClient(); localObject.OnStopClient();
// user handling // custom unspawn handler for this prefab? (for prefab pools etc.)
if (InvokeUnSpawnHandler(localObject.assetId, localObject.gameObject)) if (InvokeUnSpawnHandler(localObject.assetId, localObject.gameObject))
{ {
// reset object after user's handler // reset object after user's handler
localObject.Reset(); localObject.Reset();
} }
// default handling // otherwise fall back to default Destroy
else if (localObject.sceneId == 0) else if (localObject.sceneId == 0)
{ {
// don't call reset before destroy so that values are still set in OnDestroy // don't call reset before destroy so that values are still set in OnDestroy

View File

@ -148,8 +148,9 @@ public void FindOrSpawnObject_ErrorWhenPrefabInNullInDictionary()
Assert.IsNull(networkIdentity); Assert.IsNull(networkIdentity);
} }
// test to prevent https://github.com/vis2k/Mirror/issues/2705
[Test] [Test]
public void FindOrSpawnObject_SpawnsFromPrefabIfBothPrefabAndHandlerExists() public void FindOrSpawnObject_SpawnsFromHandlerIfBothPrefabAndHandlerExists()
{ {
const uint netId = 1003; const uint netId = 1003;
int handlerCalled = 0; int handlerCalled = 0;
@ -167,13 +168,11 @@ public void FindOrSpawnObject_SpawnsFromPrefabIfBothPrefabAndHandlerExists()
return go; return go;
}); });
bool success = NetworkClient.FindOrSpawnObject(msg, out NetworkIdentity networkIdentity); bool success = NetworkClient.FindOrSpawnObject(msg, out NetworkIdentity networkIdentity);
Assert.IsTrue(success); Assert.IsTrue(success);
Assert.IsNotNull(networkIdentity); Assert.IsNotNull(networkIdentity);
Assert.That(networkIdentity.name, Is.EqualTo($"{validPrefab.name}(Clone)")); Assert.That(handlerCalled, Is.EqualTo(1));
Assert.That(handlerCalled, Is.EqualTo(0), "Handler should not have been called");
} }
[Test] [Test]