Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question HELP: ServerRPC not being called

Discussion in 'Netcode for GameObjects' started by lavagoatGG, Jul 18, 2022.

  1. lavagoatGG

    lavagoatGG

    Joined:
    Apr 16, 2022
    Posts:
    229
    Hello,
    I am having a problem with calling a ServerRPC type function.
    I just started using Unity Netcode for Gameobjects and I am sure the solution is simple but I can't find it anywhere.
    I am trying to call a ServerRPC function on my redies.cs script from my switcher.cs script.

    I followed the documentation: lhttps://docs-multiplayer.unity3d.com/netcode/current/basics/networkvariable/index.html

    For some reason, the function isn't called. Here are my scripts:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Unity.Netcode;
    5. using System;
    6.  
    7. public class redies : NetworkBehaviour
    8. {
    9.     public NetworkList<bool> roodies = new NetworkList<bool>();
    10.  
    11.     // Start is called before the first frame update
    12.     void Start()
    13.     {
    14.        
    15.     }
    16.  
    17.     // Update is called once per frame
    18.     void Update()
    19.     {
    20.        
    21.     }
    22.  
    23.     public void OnEnable()
    24.     {
    25.         roodies.OnListChanged += onReadyChanged;
    26.     }
    27.     private void OnDisable()
    28.     {
    29.         roodies.OnListChanged -= onReadyChanged;
    30.     }
    31.  
    32.     private void onReadyChanged(NetworkListEvent<bool> listEvent)
    33.     {
    34.         //do stuff
    35.         Debug.Log("worked!");
    36.     }
    37.  
    38.     [ServerRpc(RequireOwnership = false)]
    39.     public void ChangeRedinessServerRPC(bool isReady, int location)
    40.     {
    41.         roodies[location] = isReady;
    42.     }
    43. }
    this is my redies.cs script. The last function isn't being called


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using TMPro;
    6. using Unity.Netcode;
    7.  
    8. public class switcher : NetworkBehaviour
    9. {
    10.     public bool on = false;
    11.     public Sprite On;
    12.     public Sprite Off;
    13.     public Color OnClr;
    14.     public Color offClr;
    15.  
    16.     public GameObject readyTXT;
    17.  
    18.     public redies redO;
    19.     public void Swap()
    20.     {
    21.         on = !on;
    22.  
    23.         redO.ChangeRedinessServerRPC(on,(int)NetworkManager.Singleton.LocalClientId);
    24.        
    25.         if (on)
    26.         {
    27.             gameObject.GetComponent<Image>().sprite = On;
    28.             transform.GetChild(0).GetComponent<TMP_Text>().text = "READY";
    29.             transform.GetChild(0).GetComponent<TMP_Text>().color = OnClr;
    30.         }
    31.         else
    32.         {
    33.             gameObject.GetComponent<Image>().sprite = Off;
    34.             transform.GetChild(0).GetComponent<TMP_Text>().text = "NOT READY";
    35.             transform.GetChild(0).GetComponent<TMP_Text>().color = offClr;
    36.         }
    37.     }
    38.     public void Start()
    39.     {
    40.         gameObject.GetComponent<Image>().sprite = Off;
    41.         transform.GetChild(0).GetComponent<TMP_Text>().text = "NOT READY";
    42.         transform.GetChild(0).GetComponent<TMP_Text>().color = offClr;
    43.     }
    this is my switcher.cs script. The variable redO is the redies script, I am trying to call the serverRPC function on line 23.

    What is wrong?

    Thank you
     
  2. CosmoM

    CosmoM

    Joined:
    Oct 31, 2015
    Posts:
    204
    Where are you calling swap from? Are you calling it *after* OnNetworkSpawn triggered on the objects these scripts are attached to (you should)? And are the objects that redies.cs and switcher.cs are assigned to both have networkobjects that are either scene objects or properly spawned during gameplay?
     
  3. lavagoatGG

    lavagoatGG

    Joined:
    Apr 16, 2022
    Posts:
    229
    both of the objects that redies.cs and swap.cs are assinged to have a networkObject component and they are scene objects.
    I am not sure what OnNetworkSpawn is but the script swap is called from a button In the game. You can press the button only after the NetworkManager is starting a host or a client.
     
  4. CosmoM

    CosmoM

    Joined:
    Oct 31, 2015
    Posts:
    204
    So far so good. It might be that this line:
    public redies redO;
    is what's causing this. Have you checked that during gameplay this reference is pointing to the right instance of the redies script, on both server and client? And is the serverRpc being called correctly from the server itself?
     
  5. lavagoatGG

    lavagoatGG

    Joined:
    Apr 16, 2022
    Posts:
    229
    Hello,
    I checked and the variable is pointing to the right script. I am using a host but the redies.cs script is attached to an empty game object and not to the player prefab. I am not sure how can I call the function from the server itself. If a client will connect how will he be able to call the function from the server?
     
  6. CosmoM

    CosmoM

    Joined:
    Oct 31, 2015
    Posts:
    204
    I meant, if there’s just a server, no client, is the server able to correctly call Swap(), with the ServerRpc triggering? If so, that narrows down the problem.
     
  7. lavagoatGG

    lavagoatGG

    Joined:
    Apr 16, 2022
    Posts:
    229
    I created a server only and it still doesn't call the ServerRPC function
     
    Last edited: Jul 20, 2022
  8. lavagoatGG

    lavagoatGG

    Joined:
    Apr 16, 2022
    Posts:
    229
    anyway, when creating a new script I got this error which might be relevant:
    UnityException: EditorPrefsGetInt is not allowed to be called from a MonoBehaviour constructor (or instance field initializer), call it in Awake or Start instead. Called from MonoBehaviour 'redies' on game object 'redies'.
    See "Script Serialization" page in the Unity Manual for further details.
    Unity.Collections.NativeLeakDetection.Initialize () (at <d8d38b92d94a4ff8a91e61d39c6d19cd>:0)
    Unity.Collections.NativeLeakDetection.get_Mode () (at <d8d38b92d94a4ff8a91e61d39c6d19cd>:0)
    Unity.Collections.LowLevel.Unsafe.DisposeSentinel.CreateInternal (Unity.Collections.LowLevel.Unsafe.DisposeSentinel& sentinel, System.Int32 callSiteStackDepth) (at <d8d38b92d94a4ff8a91e61d39c6d19cd>:0)
    Unity.Collections.LowLevel.Unsafe.DisposeSentinel.Create (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle& safety, Unity.Collections.LowLevel.Unsafe.DisposeSentinel& sentinel, System.Int32 callSiteStackDepth, Unity.Collections.Allocator allocator) (at <d8d38b92d94a4ff8a91e61d39c6d19cd>:0)
    Unity.Collections.NativeList`1[T].Initialize (System.Int32 initialCapacity, U& allocator, System.Int32 disposeSentinelStackDepth) (at Library/PackageCache/com.unity.collections@1.2.4/Unity.Collections/NativeList.cs:140)
    Unity.Collections.NativeList`1[T]..ctor (System.Int32 initialCapacity, Unity.Collections.AllocatorManager+AllocatorHandle allocator, System.Int32 disposeSentinelStackDepth) (at Library/PackageCache/com.unity.collections@1.2.4/Unity.Collections/NativeList.cs:174)
    Unity.Collections.NativeList`1[T]..ctor (System.Int32 initialCapacity, Unity.Collections.AllocatorManager+AllocatorHandle allocator) (at Library/PackageCache/com.unity.collections@1.2.4/Unity.Collections/NativeList.cs:116)
    Unity.Netcode.NetworkList`1[T]..ctor () (at Library/PackageCache/com.unity.netcode.gameobjects@1.0.0/Runtime/NetworkVariable/Collections/NetworkList.cs:13)
    redies..ctor () (at Assets/redies.cs:9)


    It's weird because redies is network behavior and not monobehavior
     
    Last edited: Jul 20, 2022
  9. CosmoM

    CosmoM

    Joined:
    Oct 31, 2015
    Posts:
    204
    That is weird.

    Have you tried changing
    public void OnEnable()
    to
    public override void OnNetworkSpawn()
    ? OnEnable might be too early to subscribe.
     
  10. lavagoatGG

    lavagoatGG

    Joined:
    Apr 16, 2022
    Posts:
    229
    OnNtworkInstantiate you mean?
     
  11. lavagoatGG

    lavagoatGG

    Joined:
    Apr 16, 2022
    Posts:
    229
    The problem is the function
    ChangeRedinessServerRPC
    itself just isn't being called. I don't think it's related to when I subscribe to the network variable onValueChanged
     
  12. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    656
    The UnityException: EditorPrefsGetInt relates to the network list, they don't like to be instantiated immediately. Instead of
    Code (CSharp):
    1. public NetworkList<bool> roodies = new NetworkList<bool>();
    try
    Code (CSharp):
    1.  
    2. public NetworkList<bool> roodies;
    3.  
    4. private void Awake()
    5. {
    6.      roodies = new NetworkList<bool>();
    7. }
    The fact you didn't see this before may relate to why the rpc wasn't working.
     
    lavagoatGG likes this.
  13. lavagoatGG

    lavagoatGG

    Joined:
    Apr 16, 2022
    Posts:
    229
    Before I fixed it, unity wouldn't let me build my game. Now, I can build the game. I removed the
    (RequireOwnership = false)
    from the [ServerRPC] and tried caling the function from a non-owner computer and it gave me an error saying you can't activate a serverRPC if you are not an owner. I don't understand what's happening... The function is supposed to be called when you are the owner but it doesn't get to the breakpoint I put inside it
     
  14. lavagoatGG

    lavagoatGG

    Joined:
    Apr 16, 2022
    Posts:
    229
    Okay, the problem is somhow on the script itself and not the code. I ran the ServerRPC function on a script with another name and it worked
     
  15. lavagoatGG

    lavagoatGG

    Joined:
    Apr 16, 2022
    Posts:
    229
    It's very wierd. I copied redies.cs to rpctry.cs and suddenly it works. The only difference between the scripts is their name and using System
     
  16. CosmoM

    CosmoM

    Joined:
    Oct 31, 2015
    Posts:
    204
    It might be related to the script execution order. For example, OnEnable randomly being triggered later in rpctry.cs than redies.cs. Did you try my suggestion?
     
  17. lavagoatGG

    lavagoatGG

    Joined:
    Apr 16, 2022
    Posts:
    229
    I tried your suggestion but it wasn't working. I noticed that the rpctry.cs script was attached to a gameobject without the network object component, but after I attached the component it still works
     
  18. lavagoatGG

    lavagoatGG

    Joined:
    Apr 16, 2022
    Posts:
    229
    rpctry.cs was MonoBehavior... changing it to network behavior made it not work... Why is it possible to call serverRPC from a monobehavior and not from a networkBehavior?
     
  19. lavagoatGG

    lavagoatGG

    Joined:
    Apr 16, 2022
    Posts:
    229
    I understand that in order to be able to call an RPC I need my networkObject to be spawned, but it can be only spawned from the server, and in order to tell the server to do something I need to call serverRPC... Is there any way to spawn a networkObject on the client when he connects?(without using player prefab)
     
  20. CosmoM

    CosmoM

    Joined:
    Oct 31, 2015
    Posts:
    204
    If your object is a scene object like you said, it is spawned automatically on all connecting clients. If it's not a scene object, then after instantiating it on the server you call
    .Spawn()
    on its networkobject on the server, which causes it to be spawned on all current and future clients as well.
     
  21. lavagoatGG

    lavagoatGG

    Joined:
    Apr 16, 2022
    Posts:
    229
    Thank you, it's working for now
     
    Last edited: Jul 21, 2022