diff --git a/Assets/Mirror/Core/NetworkWriterExtensions.cs b/Assets/Mirror/Core/NetworkWriterExtensions.cs index d53b6ed5b..46dec86f5 100644 --- a/Assets/Mirror/Core/NetworkWriterExtensions.cs +++ b/Assets/Mirror/Core/NetworkWriterExtensions.cs @@ -228,6 +228,22 @@ public static void WriteNetworkBehaviour(this NetworkWriter writer, NetworkBehav writer.WriteUInt(0); return; } + + // users might try to use unspawned / prefab NetworkBehaviours in + // rpcs/cmds/syncvars/messages. they would be null on the other + // end, and it might not be obvious why. let's make it obvious. + // https://github.com/vis2k/Mirror/issues/2060 + // and more recently https://github.com/MirrorNetworking/Mirror/issues/3399 + // + // => warning (instead of exception) because we also use a warning + // when writing an unspawned NetworkIdentity + if (value.netId == 0) + { + Debug.LogWarning($"Attempted to serialize unspawned NetworkBehaviour: of type {value.GetType()} on GameObject {value.name}. Prefabs and unspawned GameObjects would always be null on the other side. Please spawn it before using it in [SyncVar]s/Rpcs/Cmds/NetworkMessages etc."); + writer.WriteUInt(0); + return; + } + writer.WriteUInt(value.netId); writer.WriteByte(value.ComponentIndex); } diff --git a/Assets/Mirror/Tests/Editor/NetworkWriterTest.cs b/Assets/Mirror/Tests/Editor/NetworkWriterTest.cs index 44934a4ca..52eed3a4e 100644 --- a/Assets/Mirror/Tests/Editor/NetworkWriterTest.cs +++ b/Assets/Mirror/Tests/Editor/NetworkWriterTest.cs @@ -1451,6 +1451,25 @@ public void TestNetworkBehaviourNull() Assert.That(reader.Position, Is.EqualTo(4), "should read 4 bytes when netid is 0"); } + // test for https://github.com/MirrorNetworking/Mirror/issues/3399 + [Test] + public void TestNetworkBehaviourNotSpawned() + { + CreateNetworked(out _, out _, out RpcNetworkIdentityBehaviour component); + NetworkWriter writer = new NetworkWriter(); + writer.WriteNetworkBehaviour(component); + + byte[] bytes = writer.ToArray(); + + Assert.That(bytes.Length, Is.EqualTo(4), "unspawned Networkbehaviour should be 4 bytes long."); + + NetworkReader reader = new NetworkReader(bytes); + RpcNetworkIdentityBehaviour actual = reader.ReadNetworkBehaviour(); + Assert.That(actual, Is.Null, "should read null"); + + Assert.That(reader.Position, Is.EqualTo(4), "should read 4 bytes when netid is 0"); + } + // test to prevent https://github.com/vis2k/Mirror/issues/2972 [Test] public void TestNetworkBehaviourDoesntExistOnClient()