fix(NetworkBehaviour): Skip OnValidate in Editor Play Mode (#3852)

OnValidate only runs in Editor, but can get invoked in PlayMode if user fiddles with the inspector or by other Unity activities.
This commit is contained in:
MrGadget 2024-06-29 15:09:50 -04:00 committed by GitHub
parent fb0704c1d4
commit 49ad787d7c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 99 additions and 84 deletions

View File

@ -11,6 +11,21 @@ public class NetworkRigidbodyReliable : NetworkTransformReliable
Rigidbody rb; Rigidbody rb;
bool wasKinematic; bool wasKinematic;
protected override void OnValidate()
{
// Skip if Editor is in Play mode
if (Application.isPlaying) return;
base.OnValidate();
// we can't overwrite .target to be a Rigidbody.
// but we can ensure that .target has a Rigidbody, and use it.
if (target.GetComponent<Rigidbody>() == null)
{
Debug.LogWarning($"{name}'s NetworkRigidbody.target {target.name} is missing a Rigidbody", this);
}
}
// cach Rigidbody and original isKinematic setting // cach Rigidbody and original isKinematic setting
protected override void Awake() protected override void Awake()
{ {
@ -82,18 +97,6 @@ void FixedUpdate()
} }
} }
protected override void OnValidate()
{
base.OnValidate();
// we can't overwrite .target to be a Rigidbody.
// but we can ensure that .target has a Rigidbody, and use it.
if (target.GetComponent<Rigidbody>() == null)
{
Debug.LogWarning($"{name}'s NetworkRigidbody.target {target.name} is missing a Rigidbody", this);
}
}
protected override void OnTeleport(Vector3 destination) protected override void OnTeleport(Vector3 destination)
{ {
base.OnTeleport(destination); base.OnTeleport(destination);

View File

@ -11,6 +11,20 @@ public class NetworkRigidbodyReliable2D : NetworkTransformReliable
Rigidbody2D rb; Rigidbody2D rb;
bool wasKinematic; bool wasKinematic;
protected override void OnValidate()
{
if (Application.isPlaying) return;
base.OnValidate();
// we can't overwrite .target to be a Rigidbody.
// but we can ensure that .target has a Rigidbody, and use it.
if (target.GetComponent<Rigidbody2D>() == null)
{
Debug.LogWarning($"{name}'s NetworkRigidbody2D.target {target.name} is missing a Rigidbody2D", this);
}
}
// cach Rigidbody and original isKinematic setting // cach Rigidbody and original isKinematic setting
protected override void Awake() protected override void Awake()
{ {
@ -82,18 +96,6 @@ void FixedUpdate()
} }
} }
protected override void OnValidate()
{
base.OnValidate();
// we can't overwrite .target to be a Rigidbody.
// but we can ensure that .target has a Rigidbody, and use it.
if (target.GetComponent<Rigidbody2D>() == null)
{
Debug.LogWarning($"{name}'s NetworkRigidbody2D.target {target.name} is missing a Rigidbody2D", this);
}
}
protected override void OnTeleport(Vector3 destination) protected override void OnTeleport(Vector3 destination)
{ {
base.OnTeleport(destination); base.OnTeleport(destination);

View File

@ -11,6 +11,21 @@ public class NetworkRigidbodyUnreliable : NetworkTransformUnreliable
Rigidbody rb; Rigidbody rb;
bool wasKinematic; bool wasKinematic;
protected override void OnValidate()
{
// Skip if Editor is in Play mode
if (Application.isPlaying) return;
base.OnValidate();
// we can't overwrite .target to be a Rigidbody.
// but we can ensure that .target has a Rigidbody, and use it.
if (target.GetComponent<Rigidbody>() == null)
{
Debug.LogWarning($"{name}'s NetworkRigidbody.target {target.name} is missing a Rigidbody", this);
}
}
// cach Rigidbody and original isKinematic setting // cach Rigidbody and original isKinematic setting
protected override void Awake() protected override void Awake()
{ {
@ -82,18 +97,6 @@ void FixedUpdate()
} }
} }
protected override void OnValidate()
{
base.OnValidate();
// we can't overwrite .target to be a Rigidbody.
// but we can ensure that .target has a Rigidbody, and use it.
if (target.GetComponent<Rigidbody>() == null)
{
Debug.LogWarning($"{name}'s NetworkRigidbody.target {target.name} is missing a Rigidbody", this);
}
}
protected override void OnTeleport(Vector3 destination) protected override void OnTeleport(Vector3 destination)
{ {
base.OnTeleport(destination); base.OnTeleport(destination);

View File

@ -11,6 +11,21 @@ public class NetworkRigidbodyUnreliable2D : NetworkTransformUnreliable
Rigidbody2D rb; Rigidbody2D rb;
bool wasKinematic; bool wasKinematic;
protected override void OnValidate()
{
// Skip if Editor is in Play mode
if (Application.isPlaying) return;
base.OnValidate();
// we can't overwrite .target to be a Rigidbody.
// but we can ensure that .target has a Rigidbody, and use it.
if (target.GetComponent<Rigidbody2D>() == null)
{
Debug.LogWarning($"{name}'s NetworkRigidbody2D.target {target.name} is missing a Rigidbody2D", this);
}
}
// cach Rigidbody and original isKinematic setting // cach Rigidbody and original isKinematic setting
protected override void Awake() protected override void Awake()
{ {
@ -82,18 +97,6 @@ void FixedUpdate()
} }
} }
protected override void OnValidate()
{
base.OnValidate();
// we can't overwrite .target to be a Rigidbody.
// but we can ensure that .target has a Rigidbody, and use it.
if (target.GetComponent<Rigidbody2D>() == null)
{
Debug.LogWarning($"{name}'s NetworkRigidbody2D.target {target.name} is missing a Rigidbody2D", this);
}
}
protected override void OnTeleport(Vector3 destination) protected override void OnTeleport(Vector3 destination)
{ {
base.OnTeleport(destination); base.OnTeleport(destination);

View File

@ -98,6 +98,17 @@ public abstract class NetworkTransformBase : NetworkBehaviour
public bool showOverlay; public bool showOverlay;
public Color overlayColor = new Color(0, 0, 0, 0.5f); public Color overlayColor = new Color(0, 0, 0, 0.5f);
protected override void OnValidate()
{
// Skip if Editor is in Play mode
if (Application.isPlaying) return;
base.OnValidate();
// configure in awake
Configure();
}
// initialization ////////////////////////////////////////////////////// // initialization //////////////////////////////////////////////////////
// forcec configuration of some settings // forcec configuration of some settings
protected virtual void Configure() protected virtual void Configure()
@ -125,14 +136,6 @@ protected virtual void Awake()
Configure(); Configure();
} }
protected override void OnValidate()
{
base.OnValidate();
// configure in awake
Configure();
}
// snapshot functions ////////////////////////////////////////////////// // snapshot functions //////////////////////////////////////////////////
// get local/world position // get local/world position
protected virtual Vector3 GetPosition() => protected virtual Vector3 GetPosition() =>

View File

@ -149,6 +149,35 @@ public bool authority
// hook guard prevents that. // hook guard prevents that.
ulong syncVarHookGuard; ulong syncVarHookGuard;
protected virtual void OnValidate()
{
// Skip if Editor is in Play mode
if (Application.isPlaying) return;
// we now allow child NetworkBehaviours.
// we can not [RequireComponent(typeof(NetworkIdentity))] anymore.
// instead, we need to ensure a NetworkIdentity is somewhere in the
// parents.
// only run this in Editor. don't add more runtime overhead.
// GetComponentInParent(includeInactive) is needed because Prefabs are not
// considered active, so this check requires to scan inactive.
#if UNITY_2021_3_OR_NEWER // 2021 has GetComponentInParent(bool includeInactive = false)
if (GetComponent<NetworkIdentity>() == null &&
GetComponentInParent<NetworkIdentity>(true) == null)
{
Debug.LogError($"{GetType()} on {name} requires a NetworkIdentity. Please add a NetworkIdentity component to {name} or it's parents.", this);
}
#elif UNITY_2020_3_OR_NEWER // 2020 only has GetComponentsInParent(bool includeInactive = false), we can use this too
NetworkIdentity[] parentsIds = GetComponentsInParent<NetworkIdentity>(true);
int parentIdsCount = parentsIds != null ? parentsIds.Length : 0;
if (GetComponent<NetworkIdentity>() == null && parentIdsCount == 0)
{
Debug.LogError($"{GetType()} on {name} requires a NetworkIdentity. Please add a NetworkIdentity component to {name} or it's parents.", this);
}
#endif
}
// USED BY WEAVER to set syncvars in host mode without deadlocking // USED BY WEAVER to set syncvars in host mode without deadlocking
protected bool GetSyncVarHookGuard(ulong dirtyBit) => protected bool GetSyncVarHookGuard(ulong dirtyBit) =>
(syncVarHookGuard & dirtyBit) != 0UL; (syncVarHookGuard & dirtyBit) != 0UL;
@ -302,34 +331,6 @@ protected void InitSyncObject(SyncObject syncObject)
}; };
} }
protected virtual void OnValidate()
{
// we now allow child NetworkBehaviours.
// we can not [RequireComponent(typeof(NetworkIdentity))] anymore.
// instead, we need to ensure a NetworkIdentity is somewhere in the
// parents.
// only run this in Editor. don't add more runtime overhead.
// GetComponentInParent(includeInactive) is needed because Prefabs are not
// considered active, so this check requires to scan inactive.
#if UNITY_EDITOR
#if UNITY_2021_3_OR_NEWER // 2021 has GetComponentInParent(bool includeInactive = false)
if (GetComponent<NetworkIdentity>() == null &&
GetComponentInParent<NetworkIdentity>(true) == null)
{
Debug.LogError($"{GetType()} on {name} requires a NetworkIdentity. Please add a NetworkIdentity component to {name} or it's parents.", this);
}
#elif UNITY_2020_3_OR_NEWER // 2020 only has GetComponentsInParent(bool includeInactive = false), we can use this too
NetworkIdentity[] parentsIds = GetComponentsInParent<NetworkIdentity>(true);
int parentIdsCount = parentsIds != null ? parentsIds.Length : 0;
if (GetComponent<NetworkIdentity>() == null && parentIdsCount == 0)
{
Debug.LogError($"{GetType()} on {name} requires a NetworkIdentity. Please add a NetworkIdentity component to {name} or it's parents.", this);
}
#endif
#endif
}
// pass full function name to avoid ClassA.Func <-> ClassB.Func collisions // pass full function name to avoid ClassA.Func <-> ClassB.Func collisions
protected void SendCommandInternal(string functionFullName, int functionHashCode, NetworkWriter writer, int channelId, bool requiresAuthority = true) protected void SendCommandInternal(string functionFullName, int functionHashCode, NetworkWriter writer, int channelId, bool requiresAuthority = true)
{ {