Unity-Technologies / Unity-Technologies/com.unity.netcode.gameobjects

How about a NetworkBehaviourReference<T>?

Abierto
#2,837 1 comentario 2 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

type:feature
Lenguaje dominante
C#
Estrellas
2.3k
Forks
461
Merge medio
3 d 16 h
PR fusionados (30 d)
20

Descripción

It would be amazing if RPC arguments could just actually be any NetworkBehaviour derivative class instead of only NetworkBehaviourReference so that the compiler could enforce type on those RPC arguments instead of boilerplate cast / TryGet code.

Short of that, doing an RPC with NetworkBehaviourReference<MyNetworkBehaviourClass> at least gives me peace of mind that the compiler can catch me trying to pass the RPC a reference to a NetworkBehaviour that isn't a MyNetworkBehaviourClass.

I did it like this:

using System;
using System.Runtime.CompilerServices;

namespace Unity.Netcode
{
    public struct NetworkBehaviourReference<T> : INetworkSerializable, IEquatable<NetworkBehaviourReference<T>>
        where T : NetworkBehaviour
    {
        private NetworkObjectReference m_NetworkObjectReference;
        private ushort m_NetworkBehaviourId;

        public NetworkBehaviourReference(NetworkBehaviour networkBehaviour)
        {
            if (networkBehaviour == null)
            {
                m_NetworkObjectReference = new NetworkObjectReference((NetworkObject)null);
                m_NetworkBehaviourId = 0;
                return;
                // throw new ArgumentNullException(nameof(networkBehaviour));
            }
            if (networkBehaviour.NetworkObject == null)
            {
                throw new ArgumentException($"Cannot create {nameof(NetworkBehaviourReference<T>)} from {nameof(NetworkBehaviour)} without a {nameof(NetworkObject)}.");
            }

            m_NetworkObjectReference = networkBehaviour.NetworkObject;
            m_NetworkBehaviourId = networkBehaviour.NetworkBehaviourId;
        }

        public bool TryGet(out T networkBehaviourSubtype, NetworkManager networkManager = null)
        {
            networkBehaviourSubtype = GetInternal(this, null) as T;
            return networkBehaviourSubtype != null;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static NetworkBehaviour GetInternal(NetworkBehaviourReference<T> networkBehaviourRef, NetworkManager networkManager = null)
        {
            if (networkBehaviourRef.m_NetworkObjectReference.TryGet(out NetworkObject networkObject, networkManager))
            {
                return networkObject.GetNetworkBehaviourAtOrderIndex(networkBehaviourRef.m_NetworkBehaviourId);
            }

            return null;
        }

        public bool Equals(NetworkBehaviourReference<T> other)
        {
            return m_NetworkObjectReference.Equals(other.m_NetworkObjectReference) && m_NetworkBehaviourId == other.m_NetworkBehaviourId;
        }

        public override bool Equals(object obj)
        {
            return obj is NetworkBehaviourReference<T> other && Equals(other);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                return (m_NetworkObjectReference.GetHashCode() * 397) ^ m_NetworkBehaviourId.GetHashCode();
            }
        }

        public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
        {
            m_NetworkObjectReference.NetworkSerialize(serializer);
            serializer.SerializeValue(ref m_NetworkBehaviourId);
        }

        public static implicit operator T(NetworkBehaviourReference<T> networkBehaviourRef) => GetInternal(networkBehaviourRef) as T;

        public static implicit operator NetworkBehaviourReference<T>(T networkBehaviourSubtype) => new NetworkBehaviourReference<T>(networkBehaviourSubtype);
    }
}

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Comienza revisando NetworkBehaviourReference, NetworkObjectReference y el manejo de argumentos RPC descrito en el issue. Determina si las referencias genéricas a NetworkBehaviour o los argumentos RPC tipados directamente encajan con las rutas existentes de serialización y lookup; se considera terminado cuando las referencias tipadas se exijan y se resuelvan sin los casts actuales ni el código boilerplate de TryGet, y se haya añadido la cobertura adecuada.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
csharp, unity
Área
game-dev, networking
Tipo de issue
Nueva funcionalidad
Dificultad
5/5
Tiempo estimado
Más de una semana
Estado de actividad
Estancado
Claridad
Bastante claro
Aptitud para principiantes
25/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.