您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

113 行
5.9 KiB

using System;
using System.Runtime.CompilerServices;
namespace Unity.Netcode
{
/// <summary>
/// A helper struct for serializing <see cref="NetworkBehaviour"/>s over the network. Can be used in RPCs and <see cref="NetworkVariable{T}"/>.
/// Note: network ids get recycled by the NetworkManager after a while. So a reference pointing to
/// </summary>
public struct NetworkBehaviourReference : INetworkSerializable, IEquatable<NetworkBehaviourReference>
{
private NetworkObjectReference m_NetworkObjectReference;
private ushort m_NetworkBehaviourId;
/// <summary>
/// Creates a new instance of the <see cref="NetworkBehaviourReference{T}"/> struct.
/// </summary>
/// <param name="networkBehaviour">The <see cref="NetworkBehaviour"/> to reference.</param>
/// <exception cref="ArgumentException"></exception>
public NetworkBehaviourReference(NetworkBehaviour networkBehaviour)
{
if (networkBehaviour == null)
{
throw new ArgumentNullException(nameof(networkBehaviour));
}
if (networkBehaviour.NetworkObject == null)
{
throw new ArgumentException($"Cannot create {nameof(NetworkBehaviourReference)} from {nameof(NetworkBehaviour)} without a {nameof(NetworkObject)}.");
}
m_NetworkObjectReference = networkBehaviour.NetworkObject;
m_NetworkBehaviourId = networkBehaviour.NetworkBehaviourId;
}
/// <summary>
/// Tries to get the <see cref="NetworkBehaviour"/> referenced by this reference.
/// </summary>
/// <param name="networkBehaviour">The <see cref="NetworkBehaviour"/> which was found. Null if the corresponding <see cref="NetworkObject"/> was not found.</param>
/// <param name="networkManager">The networkmanager. Uses <see cref="NetworkManager.Singleton"/> to resolve if null.</param>
/// <returns>True if the <see cref="NetworkBehaviour"/> was found; False if the <see cref="NetworkBehaviour"/> was not found. This can happen if the corresponding <see cref="NetworkObject"/> has not been spawned yet. you can try getting the reference at a later point in time.</returns>
public bool TryGet(out NetworkBehaviour networkBehaviour, NetworkManager networkManager = null)
{
networkBehaviour = GetInternal(this, null);
return networkBehaviour != null;
}
/// <summary>
/// Tries to get the <see cref="NetworkBehaviour"/> referenced by this reference.
/// </summary>
/// <param name="networkBehaviour">The <see cref="NetworkBehaviour"/> which was found. Null if the corresponding <see cref="NetworkObject"/> was not found.</param>
/// <param name="networkManager">The networkmanager. Uses <see cref="NetworkManager.Singleton"/> to resolve if null.</param>
/// <typeparam name="T">The type of the networkBehaviour for convenience.</typeparam>
/// <returns>True if the <see cref="NetworkBehaviour"/> was found; False if the <see cref="NetworkBehaviour"/> was not found. This can happen if the corresponding <see cref="NetworkObject"/> has not been spawned yet. you can try getting the reference at a later point in time.</returns>
public bool TryGet<T>(out T networkBehaviour, NetworkManager networkManager = null) where T : NetworkBehaviour
{
networkBehaviour = GetInternal(this, null) as T;
return networkBehaviour != null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static NetworkBehaviour GetInternal(NetworkBehaviourReference networkBehaviourRef, NetworkManager networkManager = null)
{
if (networkBehaviourRef.m_NetworkObjectReference.TryGet(out NetworkObject networkObject, networkManager))
{
return networkObject.GetNetworkBehaviourAtOrderIndex(networkBehaviourRef.m_NetworkBehaviourId);
}
return null;
}
/// <inheritdoc/>
public bool Equals(NetworkBehaviourReference other)
{
return m_NetworkObjectReference.Equals(other.m_NetworkObjectReference) && m_NetworkBehaviourId == other.m_NetworkBehaviourId;
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
return obj is NetworkBehaviourReference other && Equals(other);
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (m_NetworkObjectReference.GetHashCode() * 397) ^ m_NetworkBehaviourId.GetHashCode();
}
}
/// <inheritdoc/>
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
m_NetworkObjectReference.NetworkSerialize(serializer);
serializer.SerializeValue(ref m_NetworkBehaviourId);
}
/// <summary>
/// Implicitly convert <see cref="NetworkBehaviourReference"/> to <see cref="NetworkBehaviour"/>.
/// </summary>
/// <param name="networkBehaviourRef">The <see cref="NetworkBehaviourReference"/> to convert from.</param>
/// <returns>The <see cref="NetworkBehaviour"/> this class is holding a reference to</returns>
public static implicit operator NetworkBehaviour(NetworkBehaviourReference networkBehaviourRef) => GetInternal(networkBehaviourRef);
/// <summary>
/// Implicitly convert <see cref="NetworkBehaviour"/> to <see cref="NetworkBehaviourReference"/>.
/// </summary>
/// <param name="networkBehaviour">The <see cref="NetworkBehaviour"/> to convert from.</param>
/// <returns>The <see cref="NetworkBehaviourReference"/> created from the <see cref="NetworkBehaviour"/> passed in as a parameter</returns>
public static implicit operator NetworkBehaviourReference(NetworkBehaviour networkBehaviour) => new NetworkBehaviourReference(networkBehaviour);
}
}