mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 11:00:32 +00:00
perf: SyncVar<T> some more inlining
This commit is contained in:
parent
0d55ed8448
commit
ff1199607e
@ -16,6 +16,7 @@
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mirror
|
||||
@ -33,6 +34,7 @@ public class SyncVar<T> : SyncObject, IEquatable<T>
|
||||
// virtual for SyncFieldNetworkIdentity netId trick etc.
|
||||
public virtual T Value
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _Value;
|
||||
set
|
||||
{
|
||||
@ -74,6 +76,7 @@ public virtual T Value
|
||||
// OnCallback is responsible for calling the callback.
|
||||
// this is necessary for inheriting classes like SyncVarGameObject,
|
||||
// where the netIds should be converted to GOs and call the GO hook.
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
protected virtual void InvokeCallback(T oldValue, T newValue) =>
|
||||
Callback?.Invoke(oldValue, newValue);
|
||||
|
||||
@ -107,21 +110,31 @@ public SyncVar(T value)
|
||||
// SyncVar<T>s are readonly and only initialized by 'Value' once.
|
||||
|
||||
// implicit conversion: int value = SyncVar<T>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator T(SyncVar<T> field) => field.Value;
|
||||
|
||||
// implicit conversion: SyncVar<T> = value
|
||||
// even if SyncVar<T> is readonly, it's still useful: SyncVar<int> = 1;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator SyncVar<T>(T value) => new SyncVar<T>(value);
|
||||
|
||||
// serialization (use .Value instead of _Value so hook is called!)
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void OnSerializeAll(NetworkWriter writer) => writer.Write(Value);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void OnSerializeDelta(NetworkWriter writer) => writer.Write(Value);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void OnDeserializeAll(NetworkReader reader) => Value = reader.Read<T>();
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void OnDeserializeDelta(NetworkReader reader) => Value = reader.Read<T>();
|
||||
|
||||
// IEquatable should compare Value.
|
||||
// SyncVar<T> should act invisibly like [SyncVar] before.
|
||||
// this way we can do SyncVar<int> health == 0 etc.
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Equals(T other) =>
|
||||
// from NetworkBehaviour.SyncVarEquals:
|
||||
// EqualityComparer method avoids allocations.
|
||||
|
@ -55,7 +55,9 @@ public class SyncVarGameObject : SyncVar<uint>
|
||||
// .spawned lookup from netId overwrites base uint .Value
|
||||
public new GameObject Value
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => GetGameObject(base.Value);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
set => base.Value = GetNetId(value);
|
||||
}
|
||||
|
||||
@ -64,6 +66,7 @@ public class SyncVarGameObject : SyncVar<uint>
|
||||
public new event Action<GameObject, GameObject> Callback;
|
||||
|
||||
// overwrite CallCallback to use the GameObject version instead
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
protected override void InvokeCallback(uint oldValue, uint newValue) =>
|
||||
Callback?.Invoke(GetGameObject(oldValue), GetGameObject(newValue));
|
||||
|
||||
@ -76,6 +79,7 @@ public SyncVarGameObject(GameObject value = null)
|
||||
: base(GetNetId(value)) {}
|
||||
|
||||
// helper function to get netId from GameObject (if any)
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static uint GetNetId(GameObject go)
|
||||
{
|
||||
if (go != null)
|
||||
@ -87,6 +91,7 @@ static uint GetNetId(GameObject go)
|
||||
}
|
||||
|
||||
// helper function to get GameObject from netId (if spawned)
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static GameObject GetGameObject(uint netId)
|
||||
{
|
||||
NetworkIdentity spawned = Utils.GetSpawnedInServerOrClient(netId);
|
||||
@ -94,10 +99,12 @@ static GameObject GetGameObject(uint netId)
|
||||
}
|
||||
|
||||
// implicit conversion: GameObject value = SyncFieldGameObject
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator GameObject(SyncVarGameObject field) => field.Value;
|
||||
|
||||
// implicit conversion: SyncFieldGameObject = value
|
||||
// even if SyncField is readonly, it's still useful: SyncFieldGameObject = target;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator SyncVarGameObject(GameObject value) => new SyncVarGameObject(value);
|
||||
|
||||
// == operator for comparisons like Player.target==monster
|
||||
@ -129,7 +136,10 @@ static GameObject GetGameObject(uint netId)
|
||||
public static bool operator !=(GameObject a, SyncVarGameObject b) => !(a == b);
|
||||
|
||||
// if we overwrite == operators, we also need to overwrite .Equals.
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override bool Equals(object obj) => obj is SyncVarGameObject value && this == value;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override int GetHashCode() => Value.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,9 @@ public class SyncVarNetworkBehaviour<T> : SyncVar<ulong>
|
||||
// .spawned lookup from netId overwrites base uint .Value
|
||||
public new T Value
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => ULongToNetworkBehaviour(base.Value);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
set => base.Value = NetworkBehaviourToULong(value);
|
||||
}
|
||||
|
||||
@ -34,6 +36,7 @@ public class SyncVarNetworkBehaviour<T> : SyncVar<ulong>
|
||||
public new event Action<T, T> Callback;
|
||||
|
||||
// overwrite CallCallback to use the NetworkIdentity version instead
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
protected override void InvokeCallback(ulong oldValue, ulong newValue) =>
|
||||
Callback?.Invoke(ULongToNetworkBehaviour(oldValue), ULongToNetworkBehaviour(newValue));
|
||||
|
||||
@ -46,10 +49,12 @@ public SyncVarNetworkBehaviour(T value = null)
|
||||
: base(NetworkBehaviourToULong(value)) {}
|
||||
|
||||
// implicit conversion: NetworkBehaviour value = SyncFieldNetworkBehaviour
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator T(SyncVarNetworkBehaviour<T> field) => field.Value;
|
||||
|
||||
// implicit conversion: SyncFieldNetworkBehaviour = value
|
||||
// even if SyncField is readonly, it's still useful: SyncFieldNetworkBehaviour = target;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator SyncVarNetworkBehaviour<T>(T value) => new SyncVarNetworkBehaviour<T>(value);
|
||||
|
||||
// NOTE: overloading all == operators blocks '== null' checks with an
|
||||
@ -97,16 +102,18 @@ public SyncVarNetworkBehaviour(T value = null)
|
||||
public static bool operator !=(T a, SyncVarNetworkBehaviour<T> b) => !(a == b);
|
||||
|
||||
// if we overwrite == operators, we also need to overwrite .Equals.
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override bool Equals(object obj) => obj is SyncVarNetworkBehaviour<T> value && this == value;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override int GetHashCode() => Value.GetHashCode();
|
||||
|
||||
// helper functions to get/set netId, componentIndex from ulong
|
||||
internal static ulong Pack(uint netId, byte componentIndex)
|
||||
{
|
||||
// netId on the 4 left bytes. compIndex on the right most byte.
|
||||
return (ulong)netId << 32 | componentIndex;
|
||||
}
|
||||
// netId on the 4 left bytes. compIndex on the right most byte.
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static ulong Pack(uint netId, byte componentIndex) =>
|
||||
(ulong)netId << 32 | componentIndex;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static void Unpack(ulong value, out uint netId, out byte componentIndex)
|
||||
{
|
||||
netId = (uint)(value >> 32);
|
||||
@ -133,6 +140,7 @@ static ulong NetworkBehaviourToULong(T value)
|
||||
}
|
||||
|
||||
// Serialize should only write 4+1 bytes, not 8 bytes ulong
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void OnSerializeAll(NetworkWriter writer)
|
||||
{
|
||||
Unpack(base.Value, out uint netId, out byte componentIndex);
|
||||
@ -140,10 +148,12 @@ public override void OnSerializeAll(NetworkWriter writer)
|
||||
writer.WriteByte(componentIndex);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void OnSerializeDelta(NetworkWriter writer) =>
|
||||
OnSerializeAll(writer);
|
||||
|
||||
// Deserialize should only write 4+1 bytes, not 8 bytes ulong
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void OnDeserializeAll(NetworkReader reader)
|
||||
{
|
||||
uint netId = reader.ReadUInt();
|
||||
@ -151,6 +161,7 @@ public override void OnDeserializeAll(NetworkReader reader)
|
||||
base.Value = Pack(netId, componentIndex);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void OnDeserializeDelta(NetworkReader reader) =>
|
||||
OnDeserializeAll(reader);
|
||||
}
|
||||
|
@ -48,7 +48,9 @@ public class SyncVarNetworkIdentity : SyncVar<uint>
|
||||
// .spawned lookup from netId overwrites base uint .Value
|
||||
public new NetworkIdentity Value
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => Utils.GetSpawnedInServerOrClient(base.Value);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
set => base.Value = value != null ? value.netId : 0;
|
||||
}
|
||||
|
||||
@ -57,6 +59,7 @@ public class SyncVarNetworkIdentity : SyncVar<uint>
|
||||
public new event Action<NetworkIdentity, NetworkIdentity> Callback;
|
||||
|
||||
// overwrite CallCallback to use the NetworkIdentity version instead
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
protected override void InvokeCallback(uint oldValue, uint newValue) =>
|
||||
Callback?.Invoke(Utils.GetSpawnedInServerOrClient(oldValue), Utils.GetSpawnedInServerOrClient(newValue));
|
||||
|
||||
@ -69,10 +72,12 @@ public SyncVarNetworkIdentity(NetworkIdentity value = null)
|
||||
: base(value != null ? value.netId : 0) {}
|
||||
|
||||
// implicit conversion: NetworkIdentity value = SyncFieldNetworkIdentity
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator NetworkIdentity(SyncVarNetworkIdentity field) => field.Value;
|
||||
|
||||
// implicit conversion: SyncFieldNetworkIdentity = value
|
||||
// even if SyncField is readonly, it's still useful: SyncFieldNetworkIdentity = target;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator SyncVarNetworkIdentity(NetworkIdentity value) => new SyncVarNetworkIdentity(value);
|
||||
|
||||
// NOTE: overloading all == operators blocks '== null' checks with an
|
||||
@ -104,7 +109,10 @@ public SyncVarNetworkIdentity(NetworkIdentity value = null)
|
||||
public static bool operator !=(NetworkIdentity a, SyncVarNetworkIdentity b) => !(a == b);
|
||||
|
||||
// if we overwrite == operators, we also need to overwrite .Equals.
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override bool Equals(object obj) => obj is SyncVarNetworkIdentity value && this == value;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override int GetHashCode() => Value.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user