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

How about a NetworkBehaviourReference<T>?

Aberta
#2,837 1 comentário 2 reações 0 responsáveis Ver no GitHub

Ninguém assumiu esta issue ainda.

type:feature
Linguagem predominante
C#
Estrelas
2.3k
Forks
461
Merge médio
3d 16h
PRs com merge (30d)
20

Descrição

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);
    }
}

Guia de contribuição

Abrir o guia de contribuição

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Direção de pesquisa

Comece revisando NetworkBehaviourReference, NetworkObjectReference e o tratamento de argumentos RPC descrito na issue. Determine se referências genéricas a NetworkBehaviour ou argumentos RPC diretamente tipados se encaixam nos caminhos existentes de serialização e lookup; o trabalho estará concluído quando referências tipadas forem impostas e resolvidas sem os casts atuais ou o boilerplate de TryGet, e uma cobertura adequada tiver sido adicionada.

Escrita pelo modelo de indexação a partir do texto da issue.

Avaliação

Stack de tecnologia
csharp, unity
Domínio
game-dev, networking
Tipo de issue
Funcionalidade
Dificuldade
5/5
Tempo estimado
Mais de uma semana
Status de atividade
Estagnada
Clareza
Razoavelmente clara
Facilidade para iniciantes
25/100

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.