Remove Transform/GameObject sync to avoid GetComponent calls. Use NetworkIdentity instead.

This commit is contained in:
vis2k 2020-09-28 10:50:18 +02:00
parent 717ad1e39f
commit f82d7c7abc
9 changed files with 4 additions and 613 deletions

View File

@ -84,15 +84,7 @@ public static MethodDefinition GenerateSyncVarGetter(FieldDefinition fd, string
// [SyncVar] GameObject? // [SyncVar] GameObject?
if (fd.FieldType.Is<UnityEngine.GameObject>()) if (fd.FieldType.Is<UnityEngine.GameObject>())
{ {
// return this.GetSyncVarGameObject(ref field, uint netId); Log.Error("[SyncVar] GameObject not supported anymore. Use [SyncVar] NetworkIdentity instead for: " + fd.FullName);
// this.
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldfld, netFieldId));
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldflda, fd));
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.getSyncVarGameObjectReference));
worker.Append(worker.Create(OpCodes.Ret));
} }
// [SyncVar] NetworkIdentity? // [SyncVar] NetworkIdentity?
else if (fd.FieldType.Is<NetworkIdentity>()) else if (fd.FieldType.Is<NetworkIdentity>())
@ -143,11 +135,7 @@ public static MethodDefinition GenerateSyncVarSetter(TypeDefinition td, FieldDef
// make generic version of SetSyncVar with field type // make generic version of SetSyncVar with field type
if (fd.FieldType.Is<UnityEngine.GameObject>()) if (fd.FieldType.Is<UnityEngine.GameObject>())
{ {
// reference to netId Field to set Log.Error("[SyncVar] GameObject not supported anymore. Use [SyncVar] NetworkIdentity instead for: " + fd.FullName);
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldfld, netFieldId));
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.syncVarGameObjectEqualReference));
} }
else if (fd.FieldType.Is<NetworkIdentity>()) else if (fd.FieldType.Is<NetworkIdentity>())
{ {
@ -193,11 +181,7 @@ public static MethodDefinition GenerateSyncVarSetter(TypeDefinition td, FieldDef
if (fd.FieldType.Is<UnityEngine.GameObject>()) if (fd.FieldType.Is<UnityEngine.GameObject>())
{ {
// reference to netId Field to set Log.Error("[SyncVar] GameObject not supported anymore. Use [SyncVar] NetworkIdentity instead for: " + fd.FullName);
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldflda, netFieldId));
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.setSyncVarGameObjectReference));
} }
else if (fd.FieldType.Is<NetworkIdentity>()) else if (fd.FieldType.Is<NetworkIdentity>())
{ {

View File

@ -36,12 +36,9 @@ public static class WeaverTypes
public static MethodReference syncVarEqualReference; public static MethodReference syncVarEqualReference;
public static MethodReference syncVarNetworkIdentityEqualReference; public static MethodReference syncVarNetworkIdentityEqualReference;
public static MethodReference syncVarGameObjectEqualReference;
public static MethodReference setSyncVarReference; public static MethodReference setSyncVarReference;
public static MethodReference setSyncVarHookGuard; public static MethodReference setSyncVarHookGuard;
public static MethodReference getSyncVarHookGuard; public static MethodReference getSyncVarHookGuard;
public static MethodReference setSyncVarGameObjectReference;
public static MethodReference getSyncVarGameObjectReference;
public static MethodReference setSyncVarNetworkIdentityReference; public static MethodReference setSyncVarNetworkIdentityReference;
public static MethodReference getSyncVarNetworkIdentityReference; public static MethodReference getSyncVarNetworkIdentityReference;
public static MethodReference registerCommandDelegateReference; public static MethodReference registerCommandDelegateReference;
@ -105,13 +102,10 @@ public static void SetupTargetTypes(AssemblyDefinition currentAssembly)
syncVarEqualReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "SyncVarEqual"); syncVarEqualReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "SyncVarEqual");
syncVarNetworkIdentityEqualReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "SyncVarNetworkIdentityEqual"); syncVarNetworkIdentityEqualReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "SyncVarNetworkIdentityEqual");
syncVarGameObjectEqualReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "SyncVarGameObjectEqual");
setSyncVarReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "SetSyncVar"); setSyncVarReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "SetSyncVar");
setSyncVarHookGuard = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "setSyncVarHookGuard"); setSyncVarHookGuard = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "setSyncVarHookGuard");
getSyncVarHookGuard = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "getSyncVarHookGuard"); getSyncVarHookGuard = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "getSyncVarHookGuard");
setSyncVarGameObjectReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "SetSyncVarGameObject");
getSyncVarGameObjectReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "GetSyncVarGameObject");
setSyncVarNetworkIdentityReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "SetSyncVarNetworkIdentity"); setSyncVarNetworkIdentityReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "SetSyncVarNetworkIdentity");
getSyncVarNetworkIdentityReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "GetSyncVarNetworkIdentity"); getSyncVarNetworkIdentityReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "GetSyncVarNetworkIdentity");
registerCommandDelegateReference = Resolvers.ResolveMethod(RemoteCallHelperType, currentAssembly, "RegisterCommandDelegate"); registerCommandDelegateReference = Resolvers.ResolveMethod(RemoteCallHelperType, currentAssembly, "RegisterCommandDelegate");

View File

@ -286,75 +286,6 @@ protected void SendTargetRPCInternal(NetworkConnection conn, Type invokeClass, s
#region Helpers #region Helpers
// helper function for [SyncVar] GameObjects.
// IMPORTANT: keep as 'protected', not 'internal', otherwise Weaver
// can't resolve it
[EditorBrowsable(EditorBrowsableState.Never)]
protected bool SyncVarGameObjectEqual(GameObject newGameObject, uint netIdField)
{
uint newNetId = 0;
if (newGameObject != null)
{
NetworkIdentity identity = newGameObject.GetComponent<NetworkIdentity>();
if (identity != null)
{
newNetId = identity.netId;
if (newNetId == 0)
{
Debug.LogWarning("SetSyncVarGameObject GameObject " + newGameObject + " has a zero netId. Maybe it is not spawned yet?");
}
}
}
return newNetId == netIdField;
}
// helper function for [SyncVar] GameObjects.
[EditorBrowsable(EditorBrowsableState.Never)]
protected void SetSyncVarGameObject(GameObject newGameObject, ref GameObject gameObjectField, ulong dirtyBit, ref uint netIdField)
{
if (getSyncVarHookGuard(dirtyBit))
return;
uint newNetId = 0;
if (newGameObject != null)
{
NetworkIdentity identity = newGameObject.GetComponent<NetworkIdentity>();
if (identity != null)
{
newNetId = identity.netId;
if (newNetId == 0)
{
Debug.LogWarning("SetSyncVarGameObject GameObject " + newGameObject + " has a zero netId. Maybe it is not spawned yet?");
}
}
}
// logger.Log("SetSyncVar GameObject " + GetType().Name + " bit [" + dirtyBit + "] netfieldId:" + netIdField + "->" + newNetId);
SetDirtyBit(dirtyBit);
// assign new one on the server, and in case we ever need it on client too
gameObjectField = newGameObject;
netIdField = newNetId;
}
// helper function for [SyncVar] GameObjects.
// -> ref GameObject as second argument makes OnDeserialize processing easier
[EditorBrowsable(EditorBrowsableState.Never)]
protected GameObject GetSyncVarGameObject(uint netId, ref GameObject gameObjectField)
{
// server always uses the field
if (isServer)
{
return gameObjectField;
}
// client always looks up based on netId because objects might get in and out of range
// over and over again, which shouldn't null them forever
if (NetworkIdentity.spawned.TryGetValue(netId, out NetworkIdentity identity) && identity != null)
return gameObjectField = identity.gameObject;
return null;
}
// helper function for [SyncVar] NetworkIdentities. // helper function for [SyncVar] NetworkIdentities.
// IMPORTANT: keep as 'protected', not 'internal', otherwise Weaver // IMPORTANT: keep as 'protected', not 'internal', otherwise Weaver
// can't resolve it // can't resolve it

View File

@ -288,19 +288,6 @@ public static byte[] ReadBytes(this NetworkReader reader, int count)
} }
public static Guid ReadGuid(this NetworkReader reader) => new Guid(reader.ReadBytes(16)); public static Guid ReadGuid(this NetworkReader reader) => new Guid(reader.ReadBytes(16));
public static Transform ReadTransform(this NetworkReader reader)
{
// Dont use null propagation here as it could lead to MissingReferenceException
NetworkIdentity networkIdentity = reader.ReadNetworkIdentity();
return networkIdentity != null ? networkIdentity.transform : null;
}
public static GameObject ReadGameObject(this NetworkReader reader)
{
// Dont use null propagation here as it could lead to MissingReferenceException
NetworkIdentity networkIdentity = reader.ReadNetworkIdentity();
return networkIdentity != null ? networkIdentity.gameObject : null;
}
public static NetworkIdentity ReadNetworkIdentity(this NetworkReader reader) public static NetworkIdentity ReadNetworkIdentity(this NetworkReader reader)
{ {

View File

@ -412,44 +412,6 @@ public static void WriteNetworkIdentity(this NetworkWriter writer, NetworkIdenti
writer.WriteUInt32(value.netId); writer.WriteUInt32(value.netId);
} }
public static void WriteTransform(this NetworkWriter writer, Transform value)
{
if (value == null)
{
writer.WriteUInt32(0);
return;
}
NetworkIdentity identity = value.GetComponent<NetworkIdentity>();
if (identity != null)
{
writer.WriteUInt32(identity.netId);
}
else
{
Debug.LogWarning("NetworkWriter " + value + " has no NetworkIdentity");
writer.WriteUInt32(0);
}
}
public static void WriteGameObject(this NetworkWriter writer, GameObject value)
{
if (value == null)
{
writer.WriteUInt32(0);
return;
}
NetworkIdentity identity = value.GetComponent<NetworkIdentity>();
if (identity != null)
{
writer.WriteUInt32(identity.netId);
}
else
{
Debug.LogWarning("NetworkWriter " + value + " has no NetworkIdentity");
writer.WriteUInt32(0);
}
}
public static void WriteUri(this NetworkWriter writer, Uri uri) public static void WriteUri(this NetworkWriter writer, Uri uri)
{ {
writer.WriteString(uri.ToString()); writer.WriteString(uri.ToString());

View File

@ -7,14 +7,6 @@ namespace Mirror.Tests
{ {
class EmptyBehaviour : NetworkBehaviour { } class EmptyBehaviour : NetworkBehaviour { }
class SyncVarGameObjectEqualExposedBehaviour : NetworkBehaviour
{
public bool SyncVarGameObjectEqualExposed(GameObject newGameObject, uint netIdField)
{
return SyncVarGameObjectEqual(newGameObject, netIdField);
}
}
class SyncVarNetworkIdentityEqualExposedBehaviour : NetworkBehaviour class SyncVarNetworkIdentityEqualExposedBehaviour : NetworkBehaviour
{ {
public bool SyncVarNetworkIdentityEqualExposed(NetworkIdentity newNetworkIdentity, uint netIdField) public bool SyncVarNetworkIdentityEqualExposed(NetworkIdentity newNetworkIdentity, uint netIdField)
@ -90,36 +82,6 @@ public static void Delegate(NetworkBehaviour comp, NetworkReader reader, Network
public static void Delegate2(NetworkBehaviour comp, NetworkReader reader, NetworkConnection senderConnection) { } public static void Delegate2(NetworkBehaviour comp, NetworkReader reader, NetworkConnection senderConnection) { }
} }
// we need to inherit from networkbehaviour to test protected functions
public class NetworkBehaviourSetSyncVarGameObjectComponent : NetworkBehaviour
{
//[SyncVar]
public GameObject test;
// usually generated by weaver
public uint testNetId;
// SetSyncVarGameObject wrapper to expose it
public void SetSyncVarGameObjectExposed(GameObject newGameObject, ulong dirtyBit)
{
SetSyncVarGameObject(newGameObject, ref test, dirtyBit, ref testNetId);
}
}
// we need to inherit from networkbehaviour to test protected functions
public class NetworkBehaviourGetSyncVarGameObjectComponent : NetworkBehaviour
{
//[SyncVar]
public GameObject test;
// usually generated by weaver
public uint testNetId;
// SetSyncVarGameObject wrapper to expose it
public GameObject GetSyncVarGameObjectExposed()
{
return GetSyncVarGameObject(testNetId, ref test);
}
}
// we need to inherit from networkbehaviour to test protected functions // we need to inherit from networkbehaviour to test protected functions
public class NetworkBehaviourSetSyncVarNetworkIdentityComponent : NetworkBehaviour public class NetworkBehaviourSetSyncVarNetworkIdentityComponent : NetworkBehaviour
{ {
@ -632,140 +594,6 @@ public void GetDelegate()
RemoteCallHelper.RemoveDelegate(registeredHash); RemoteCallHelper.RemoveDelegate(registeredHash);
} }
// NOTE: SyncVarGameObjectEqual should be static later
[Test]
public void SyncVarGameObjectEqualZeroNetIdNullIsTrue()
{
// null and identity.netid==0 returns true (=equal)
//
// later we should reevaluate if this is so smart or not. might be
// better to return false here.
// => we possibly return false so that resync doesn't happen when
// GO disappears? or not?
SyncVarGameObjectEqualExposedBehaviour comp = gameObject.AddComponent<SyncVarGameObjectEqualExposedBehaviour>();
bool result = comp.SyncVarGameObjectEqualExposed(null, identity.netId);
Assert.That(result, Is.True);
}
// NOTE: SyncVarGameObjectEqual should be static later
[Test]
public void SyncVarGameObjectEqualNull()
{
// our identity should have a netid for comparing
identity.netId = 42;
// null should return false
SyncVarGameObjectEqualExposedBehaviour comp = gameObject.AddComponent<SyncVarGameObjectEqualExposedBehaviour>();
bool result = comp.SyncVarGameObjectEqualExposed(null, identity.netId);
Assert.That(result, Is.False);
}
// NOTE: SyncVarGameObjectEqual should be static later
[Test]
public void SyncVarGameObjectEqualZeroNetIdAndGOWithoutIdentityComponentIsTrue()
{
// null and identity.netid==0 returns true (=equal)
//
// later we should reevaluate if this is so smart or not. might be
// better to return false here.
// => we possibly return false so that resync doesn't happen when
// GO disappears? or not?
GameObject go = new GameObject();
SyncVarGameObjectEqualExposedBehaviour comp = go.AddComponent<SyncVarGameObjectEqualExposedBehaviour>();
bool result = comp.SyncVarGameObjectEqualExposed(go, identity.netId);
Assert.That(result, Is.True);
}
// NOTE: SyncVarGameObjectEqual should be static later
[Test]
public void SyncVarGameObjectEqualWithoutIdentityComponent()
{
// our identity should have a netid for comparing
identity.netId = 42;
// gameobject without networkidentity component should return false
GameObject go = new GameObject();
SyncVarGameObjectEqualExposedBehaviour comp = go.AddComponent<SyncVarGameObjectEqualExposedBehaviour>();
bool result = comp.SyncVarGameObjectEqualExposed(go, identity.netId);
Assert.That(result, Is.False);
// clean up
GameObject.DestroyImmediate(go);
}
// NOTE: SyncVarGameObjectEqual should be static later
[Test]
public void SyncVarGameObjectEqualValidGOWithDifferentNetId()
{
// our identity should have a netid for comparing
identity.netId = 42;
// gameobject with valid networkidentity and netid that is different
GameObject go = new GameObject();
NetworkIdentity ni = go.AddComponent<NetworkIdentity>();
SyncVarGameObjectEqualExposedBehaviour comp = go.AddComponent<SyncVarGameObjectEqualExposedBehaviour>();
ni.netId = 43;
bool result = comp.SyncVarGameObjectEqualExposed(go, identity.netId);
Assert.That(result, Is.False);
// clean up
GameObject.DestroyImmediate(go);
}
// NOTE: SyncVarGameObjectEqual should be static later
[Test]
public void SyncVarGameObjectEqualValidGOWithSameNetId()
{
// our identity should have a netid for comparing
identity.netId = 42;
// gameobject with valid networkidentity and netid that is different
GameObject go = new GameObject();
NetworkIdentity ni = go.AddComponent<NetworkIdentity>();
SyncVarGameObjectEqualExposedBehaviour comp = go.AddComponent<SyncVarGameObjectEqualExposedBehaviour>();
ni.netId = 42;
bool result = comp.SyncVarGameObjectEqualExposed(go, identity.netId);
Assert.That(result, Is.True);
// clean up
GameObject.DestroyImmediate(go);
}
// NOTE: SyncVarGameObjectEqual should be static later
[Test]
public void SyncVarGameObjectEqualUnspawnedGO()
{
// our identity should have a netid for comparing
identity.netId = 42;
// gameobject with valid networkidentity and 0 netid that is unspawned
GameObject go = new GameObject();
go.AddComponent<NetworkIdentity>();
SyncVarGameObjectEqualExposedBehaviour comp = go.AddComponent<SyncVarGameObjectEqualExposedBehaviour>();
LogAssert.Expect(LogType.Warning, "SetSyncVarGameObject GameObject " + go + " has a zero netId. Maybe it is not spawned yet?");
bool result = comp.SyncVarGameObjectEqualExposed(go, identity.netId);
Assert.That(result, Is.False);
// clean up
GameObject.DestroyImmediate(go);
}
// NOTE: SyncVarGameObjectEqual should be static later
[Test]
public void SyncVarGameObjectEqualUnspawnedGOZeroNetIdIsTrue()
{
// unspawned go and identity.netid==0 returns true (=equal)
GameObject go = new GameObject();
go.AddComponent<NetworkIdentity>();
SyncVarGameObjectEqualExposedBehaviour comp = go.AddComponent<SyncVarGameObjectEqualExposedBehaviour>();
LogAssert.Expect(LogType.Warning, "SetSyncVarGameObject GameObject " + go + " has a zero netId. Maybe it is not spawned yet?");
bool result = comp.SyncVarGameObjectEqualExposed(go, identity.netId);
Assert.That(result, Is.True);
// clean up
GameObject.DestroyImmediate(go);
}
// NOTE: SyncVarNetworkIdentityEqual should be static later // NOTE: SyncVarNetworkIdentityEqual should be static later
[Test] [Test]
public void SyncVarNetworkIdentityEqualZeroNetIdNullIsTrue() public void SyncVarNetworkIdentityEqualZeroNetIdNullIsTrue()
@ -867,239 +695,6 @@ public void SyncVarNetworkIdentityEqualUnspawnedIdentityZeroNetIdIsTrue()
GameObject.DestroyImmediate(go); GameObject.DestroyImmediate(go);
} }
[Test]
public void SetSyncVarGameObjectWithValidObject()
{
// add test component
NetworkBehaviourSetSyncVarGameObjectComponent comp = gameObject.AddComponent<NetworkBehaviourSetSyncVarGameObjectComponent>();
// for isDirty check
comp.syncInterval = 0;
// create a valid GameObject with networkidentity and netid
GameObject go = new GameObject();
NetworkIdentity ni = go.AddComponent<NetworkIdentity>();
ni.netId = 43;
// set the GameObject SyncVar
Assert.That(comp.IsDirty(), Is.False);
comp.SetSyncVarGameObjectExposed(go, 1ul);
Assert.That(comp.test, Is.EqualTo(go));
Assert.That(comp.testNetId, Is.EqualTo(ni.netId));
Assert.That(comp.IsDirty(), Is.True);
// clean up
GameObject.DestroyImmediate(go);
}
[Test]
public void SetSyncVarGameObjectNull()
{
// add test component
NetworkBehaviourSetSyncVarGameObjectComponent comp = gameObject.AddComponent<NetworkBehaviourSetSyncVarGameObjectComponent>();
// for isDirty check
comp.syncInterval = 0;
// set some existing GO+netId first to check if it is going to be
// overwritten
GameObject go = new GameObject();
comp.test = go;
comp.testNetId = 43;
// set the GameObject SyncVar to null
Assert.That(comp.IsDirty(), Is.False);
comp.SetSyncVarGameObjectExposed(null, 1ul);
Assert.That(comp.test, Is.EqualTo(null));
Assert.That(comp.testNetId, Is.EqualTo(0));
Assert.That(comp.IsDirty(), Is.True);
// clean up
GameObject.DestroyImmediate(go);
}
[Test]
public void SetSyncVarGameObjectWithoutNetworkIdentity()
{
// add test component
NetworkBehaviourSetSyncVarGameObjectComponent comp = gameObject.AddComponent<NetworkBehaviourSetSyncVarGameObjectComponent>();
// for isDirty check
comp.syncInterval = 0;
// set some existing GO+netId first to check if it is going to be
// overwritten
GameObject go = new GameObject();
comp.test = go;
comp.testNetId = 43;
// create test GO with no networkidentity
GameObject test = new GameObject();
// set the GameObject SyncVar to 'test' GO without netidentity.
// -> the way it currently works is that it sets netId to 0, but
// it DOES set gameObjectField to the GameObject without the
// NetworkIdentity, instead of setting it to null because it's
// seemingly invalid.
// -> there might be a deeper reason why UNET did that. perhaps for
// cases where we assign a GameObject before the network was
// fully started and has no netId or networkidentity yet etc.
// => it works, so let's keep it for now
Assert.That(comp.IsDirty(), Is.False);
comp.SetSyncVarGameObjectExposed(test, 1ul);
Assert.That(comp.test, Is.EqualTo(test));
Assert.That(comp.testNetId, Is.EqualTo(0));
Assert.That(comp.IsDirty(), Is.True);
// clean up
GameObject.DestroyImmediate(test);
GameObject.DestroyImmediate(go);
}
[Test]
public void SetSyncVarGameObjectZeroNetId()
{
// add test component
NetworkBehaviourSetSyncVarGameObjectComponent comp = gameObject.AddComponent<NetworkBehaviourSetSyncVarGameObjectComponent>();
// for isDirty check
comp.syncInterval = 0;
// set some existing GO+netId first to check if it is going to be
// overwritten
GameObject go = new GameObject();
comp.test = go;
comp.testNetId = 43;
// create test GO with networkidentity and zero netid
GameObject test = new GameObject();
NetworkIdentity ni = test.AddComponent<NetworkIdentity>();
Assert.That(ni.netId, Is.EqualTo(0));
// set the GameObject SyncVar to 'test' GO with zero netId.
// -> the way it currently works is that it sets netId to 0, but
// it DOES set gameObjectField to the GameObject without the
// NetworkIdentity, instead of setting it to null because it's
// seemingly invalid.
// -> there might be a deeper reason why UNET did that. perhaps for
// cases where we assign a GameObject before the network was
// fully started and has no netId or networkidentity yet etc.
// => it works, so let's keep it for now
Assert.That(comp.IsDirty(), Is.False);
LogAssert.Expect(LogType.Warning, "SetSyncVarGameObject GameObject " + test + " has a zero netId. Maybe it is not spawned yet?");
comp.SetSyncVarGameObjectExposed(test, 1ul);
Assert.That(comp.test, Is.EqualTo(test));
Assert.That(comp.testNetId, Is.EqualTo(0));
Assert.That(comp.IsDirty(), Is.True);
// clean up
GameObject.DestroyImmediate(test);
GameObject.DestroyImmediate(go);
}
[Test]
public void GetSyncVarGameObjectOnServer()
{
// call OnStartServer so isServer is true
identity.OnStartServer();
Assert.That(identity.isServer, Is.True);
// add test component
NetworkBehaviourGetSyncVarGameObjectComponent comp = gameObject.AddComponent<NetworkBehaviourGetSyncVarGameObjectComponent>();
// for isDirty check
comp.syncInterval = 0;
// create a syncable GameObject
GameObject go = new GameObject();
NetworkIdentity ni = go.AddComponent<NetworkIdentity>();
ni.netId = identity.netId + 1;
// assign it in the component
comp.test = go;
comp.testNetId = ni.netId;
// get it on the server. should simply return the field instead of
// doing any netId lookup like on the client
GameObject result = comp.GetSyncVarGameObjectExposed();
Assert.That(result, Is.EqualTo(go));
// clean up: set isServer false first, otherwise Destroy instead of DestroyImmediate is called
identity.netId = 0;
GameObject.DestroyImmediate(go);
}
[Test]
public void GetSyncVarGameObjectOnServerNull()
{
// call OnStartServer and assign netId so isServer is true
identity.OnStartServer();
Assert.That(identity.isServer, Is.True);
// add test component
NetworkBehaviourGetSyncVarGameObjectComponent comp = gameObject.AddComponent<NetworkBehaviourGetSyncVarGameObjectComponent>();
// for isDirty check
comp.syncInterval = 0;
// get it on the server. null should work fine.
GameObject result = comp.GetSyncVarGameObjectExposed();
Assert.That(result, Is.Null);
}
[Test]
public void GetSyncVarGameObjectOnClient()
{
// are we on client and not on server?
identity.isClient = true;
Assert.That(identity.isServer, Is.False);
// add test component
NetworkBehaviourGetSyncVarGameObjectComponent comp = gameObject.AddComponent<NetworkBehaviourGetSyncVarGameObjectComponent>();
// for isDirty check
comp.syncInterval = 0;
// create a syncable GameObject
GameObject go = new GameObject();
NetworkIdentity ni = go.AddComponent<NetworkIdentity>();
ni.netId = 43;
// register in spawned dict because clients should look it up via
// netId
NetworkIdentity.spawned[ni.netId] = ni;
// assign ONLY netId in the component. assume that GameObject was
// assigned earlier but client walked so far out of range that it
// was despawned on the client. so it's forced to do the netId look-
// up.
Assert.That(comp.test, Is.Null);
comp.testNetId = ni.netId;
// get it on the client. should look up netId in spawned
GameObject result = comp.GetSyncVarGameObjectExposed();
Assert.That(result, Is.EqualTo(go));
// clean up
NetworkServer.Shutdown();
Transport.activeTransport = null;
GameObject.DestroyImmediate(go);
}
[Test]
public void GetSyncVarGameObjectOnClientNull()
{
// are we on client and not on server?
identity.isClient = true;
Assert.That(identity.isServer, Is.False);
// add test component
NetworkBehaviourGetSyncVarGameObjectComponent comp = gameObject.AddComponent<NetworkBehaviourGetSyncVarGameObjectComponent>();
// for isDirty check
comp.syncInterval = 0;
// get it on the client. null should be supported.
GameObject result = comp.GetSyncVarGameObjectExposed();
Assert.That(result, Is.Null);
// clean up
NetworkServer.Shutdown();
Transport.activeTransport = null;
}
[Test] [Test]
public void SetSyncVarNetworkIdentityWithValidObject() public void SetSyncVarNetworkIdentityWithValidObject()
{ {

View File

@ -18,19 +18,6 @@ void OnValueChanged(int oldValue, int newValue)
} }
} }
class GameObjectHookBehaviour : NetworkBehaviour
{
[SyncVar(hook = nameof(OnValueChanged))]
public GameObject value = null;
public event Action<GameObject, GameObject> HookCalled;
void OnValueChanged(GameObject oldValue, GameObject newValue)
{
HookCalled.Invoke(oldValue, newValue);
}
}
class NetworkIdentityHookBehaviour : NetworkBehaviour class NetworkIdentityHookBehaviour : NetworkBehaviour
{ {
[SyncVar(hook = nameof(OnValueChanged))] [SyncVar(hook = nameof(OnValueChanged))]
@ -141,7 +128,7 @@ NetworkIdentity CreateNetworkIdentity(uint netId)
} }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <param name="serverObject"></param> /// <param name="serverObject"></param>
@ -242,33 +229,6 @@ public void StaticMethod_HookCalledWhenSyncingChangedValue(bool intialState)
Assert.That(hookcallCount, Is.EqualTo(1)); Assert.That(hookcallCount, Is.EqualTo(1));
} }
[Test]
[TestCase(true)]
[TestCase(false)]
public void GameObjectHook_HookCalledWhenSyncingChangedValue(bool intialState)
{
GameObjectHookBehaviour serverObject = CreateObject<GameObjectHookBehaviour>();
GameObjectHookBehaviour clientObject = CreateObject<GameObjectHookBehaviour>();
GameObject clientValue = null;
GameObject serverValue = CreateNetworkIdentity(2032).gameObject;
serverObject.value = serverValue;
clientObject.value = clientValue;
int callCount = 0;
clientObject.HookCalled += (oldValue, newValue) =>
{
callCount++;
Assert.That(oldValue, Is.EqualTo(clientValue));
Assert.That(newValue, Is.EqualTo(serverValue));
};
bool written = SyncToClient(serverObject, clientObject, intialState);
Assert.IsTrue(written);
Assert.That(callCount, Is.EqualTo(1));
}
[Test] [Test]
[TestCase(true)] [TestCase(true)]
[TestCase(false)] [TestCase(false)]

View File

@ -22,12 +22,6 @@ public void FindsStaticHook()
IsSuccess(); IsSuccess();
} }
[Test]
public void FindsHookWithGameObjects()
{
IsSuccess();
}
[Test] [Test]
public void FindsHookWithNetworkIdentity() public void FindsHookWithNetworkIdentity()
{ {

View File

@ -1,16 +0,0 @@
using Mirror;
using UnityEngine;
namespace WeaverSyncVarHookTests.FindsHookWithGameObjects
{
class FindsHookWithGameObjects : NetworkBehaviour
{
[SyncVar(hook = nameof(onTargetChanged))]
GameObject target;
void onTargetChanged(GameObject oldValue, GameObject newValue)
{
}
}
}