Skip to content

ServerRPC request method not found #540

@mnicolas94

Description

@mnicolas94

Describe the bug
I have gameobject in the scene, lets call it GO1, with a NetworkedBehaviour inherited class named GoToScenesList. Then, i have another gameobject, lets call it GO2, also with a NetworkedBehaviour inherited class named NetEventManager. When i try to call a serverRPC from a client in GoToScenesList script im getting "ServerRPC request method not found" error on the server, and if i call a clientRpc i get "ClientRPC request method not found" on the clients. The weird part is that if i remove the GO2 object from the scene, everything works fine. Both objects have their own NetworkedObject component, and they are not related at all in the scene hierarchy.

To Reproduce
this the code for GoToScenesList script:
`
using System;
using System.Collections.Generic;
using MLAPI;
using MLAPI.Messaging;
using NIS.Runtime.Lobby;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

namespace Samples.LobbySample
{
public class GoToScenesList : NetworkedBehaviour
{
public Action eventSceneChanged;
public Action eventReturnedToLobby;

    public LobbyManager lobbyManager;
 
    public List<string> scenes;
    public GameObject scenesLayout;
    public Button buttonPrefab;
    public Button backToLobby;
    
    private string _currentSceneLoaded;

    void Start()
    {
        lobbyManager.eventLostConnectionToServer += OnDisconnectedToServer;
        backToLobby.onClick.AddListener(GoBackToLobby);
        PopulateScenesButtons();
        
        var no = GetComponentInParent<NetworkedObject>();
        print($"{name}-{no}");
    }

    private void OnDisconnectedToServer()
    {
        RemoveCurrentScene();
    }

    private void PopulateScenesButtons()
    {
        foreach (var scene in scenes)
        {
            var button = Instantiate(buttonPrefab, scenesLayout.transform);
            var text = button.GetComponentInChildren<TextMeshProUGUI>();
        
            button.onClick.AddListener(() => GoToScene(scene));
            text.text = scene;
        }
    }

    [ServerRPC(RequireOwnership = false)]
    private void ServerRequestSceneChangeOnClients(string sceneName)  // this is the serverRpc that is not founded
    {
        InvokeClientRpcOnEveryone(ClientChangeScene, sceneName);
    }

    [ServerRPC(RequireOwnership = false)]
    private void ServerRequestGoBackToLobby()
    {
        InvokeClientRpcOnEveryone(ClientGoBackToLobby);
    }

    [ClientRPC]
    private void ClientChangeScene(string sceneName)  // this is the clientRpc that is not founded
    {
        _currentSceneLoaded = sceneName;
        SceneManager.LoadScene(sceneName, LoadSceneMode.Additive);
        eventSceneChanged?.Invoke();
    }

    [ClientRPC]
    private void ClientGoBackToLobby()
    {
        RemoveCurrentScene();
        eventReturnedToLobby?.Invoke();
    }

    private void RemoveCurrentScene()
    {
        SceneManager.UnloadSceneAsync(_currentSceneLoaded);
    }
    
    private void GoToScene(string scene)
    {
        InvokeServerRpc(ServerRequestSceneChangeOnClients, scene);
    }

    private void GoBackToLobby()
    {
        InvokeServerRpc(ServerRequestGoBackToLobby);
    }
}

}`

this is the NetEventManager code:

`using System;
using System.Collections.Generic;
using System.IO;
using MLAPI;
using MLAPI.Logging;
using MLAPI.Messaging;
using MLAPI.Serialization.Pooled;
using UnityEngine;

namespace NIS.Runtime.Events
{
public class NetEventManager : NetworkedBehaviour
{
public delegate void SendMessageToManager(string hash, int index, Stream message);

    private static NetEventManager _instance;
    public static NetEventManager Instance => _instance;

    private Dictionary<string, List<NetEvent>> _registeredNetEvents;

    private void Awake()
    {
        if (_instance == null)
        {
            _instance = this;
        }
        else if (_instance != this)
        {
            Destroy(gameObject);
        }
        
        _registeredNetEvents = new Dictionary<string, List<NetEvent>>();

        var no = GetComponentInParent<NetworkedObject>();
        print($"{name}-{no}");
    }

    [ServerRPC(RequireOwnership = false)]
    private void HandleBroadcastTypeAndSendToClients(ulong sender, Stream payload)
    {
        using (PooledBitReader pooledBitReader = PooledBitReader.Get(payload))
        {
            BroadcastType btype = (BroadcastType) pooledBitReader.ReadByte();

            switch (btype)
            {
                case BroadcastType.All:
                    InvokeClientRpcOnEveryonePerformance(ClientHandleMessage, payload);
                    if (!IsHost)  // dedicated server
                    {
                        HandleMessage(NetworkingManager.Singleton.ServerClientId, payload);
                    }
                    break;
                case BroadcastType.Local:
                    InvokeClientRpcOnClientPerformance(ClientHandleMessage, sender, payload);
                    break;
                case BroadcastType.Others:
                    InvokeClientRpcOnEveryoneExceptPerformance(ClientHandleMessage, sender, payload);
                    break;
                case BroadcastType.ClientsOnly:
                    InvokeClientRpcOnEveryonePerformance(ClientHandleMessage, payload);  
                    break;
                case BroadcastType.ServerOnly:
                    HandleMessage(NetworkingManager.Singleton.ServerClientId, payload);
                    break;
            }
        }
    }

    private void SendMessageToServerFromNetEvent(string hash, int index, Stream stream)
    {
        if (IsServer)
        {
            HandleBroadcastTypeAndSendToClients(NetworkingManager.Singleton.ServerClientId, stream);
        }
        else if (IsClient)
        {
            InvokeServerRpcPerformance(HandleBroadcastTypeAndSendToClients, stream);
        }
    }

    [ClientRPC]
    private void ClientHandleMessage(ulong sender, Stream stream)
    {
        HandleMessage(sender, stream);
    }
    
    private void HandleMessage(ulong sender, Stream stream)
    {
        using (PooledBitReader pooledBitReader = PooledBitReader.Get(stream))
        {
            string hash = pooledBitReader.ReadString(true).ToString();
            int index = pooledBitReader.ReadInt16();

            if (_registeredNetEvents.ContainsKey(hash))
            {
                var eventsList = _registeredNetEvents[hash];
                if (index < eventsList.Count)
                {
                    eventsList[index].ReceiveMessageFromManager(sender, stream);
                }
                else
                {
                    NetworkLog.LogWarningServer($"NetEvent not founded for index {index} and hash {hash}");
                }
            }
            else
            {
                NetworkLog.LogWarningServer($"NetEvent not founded for hash {hash}");
            }
        }
    }

    public T CreateNetEvent<T>(Component parent) where T : NetEvent
    {
        string hash = GetHashFromParent(parent);
        var netEvent = RegisterNewNetEvent<T>(hash);
        
        return netEvent;
    }

    private T RegisterNewNetEvent<T>(string hash) where T : NetEvent
    {
        if (!_registeredNetEvents.ContainsKey(hash))
        {
            var newNetEventList = new List<NetEvent>();
            _registeredNetEvents.Add(hash, newNetEventList);
        }

        var netEventList = _registeredNetEvents[hash];

        int index = netEventList.Count;
        
        var netEvent = Activator.CreateInstance(
            typeof(T), hash, index, (SendMessageToManager) SendMessageToServerFromNetEvent) as T;
        netEventList.Add(netEvent);
        return netEvent;
    }

    private string GetHashFromParent(Component parent)
    {
        var netObj = parent.GetComponent<NetworkedObject>();
        if (netObj == null)
        {
            throw new ArgumentException("Could not get NetworkedObject for the parent component." +
                                        " Are you missing a NetworkedObject component?");
        }

        ulong netId = netObj.NetworkId;
        int componentOrder = GetComponentOrderIndex(parent);

        return $"{netId}-{componentOrder}";
    }

    private int GetComponentOrderIndex(Component component)
    {
        Component[] components = component.gameObject.GetComponents<Component>();
        for (int i = 0; i < components.Length; i++)
        {
            var comp = (UnityEngine.Object) components[i];
            if (comp == (UnityEngine.Object) component)
            {
                return i;
            }
        }

        return 0;
    }
}

}`

Expected behavior
I expected to not get that error

Screenshots
hierarchy screenshot
hierarchy

NetWorkingManager configuration 1
networkingmanager_config_1

NetWorkingManager configuration 2
networkingmanager_config_2

Environment (please complete the following information):

  • OS: Windows 10
  • Unity Version: 2019.3.0f6
  • MLAPI Version: v12.1.7

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions