Search Unity

Client Running Server RPC function

Discussion in 'Multiplayer' started by Ukutura, Apr 13, 2022.

  1. Ukutura

    Ukutura

    Joined:
    Jan 16, 2022
    Posts:
    10
    Hi everyone,

    I'm a unity noob trying to have two players sync up. Right now it looks like the client is running the ServerRPC function, causing an error because clients aren't allowed to write to network variables.

    I have the following code:


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Unity.Netcode;
    5.  
    6. public class scr_PlayerMovingState : scr_PlayerBaseState
    7. {
    8.     private Animator thisAnimator;
    9.     scr_PlayerStateManager playerReferenceToUseInServerRPC;
    10.  
    11.     public override void EnterState(scr_PlayerStateManager player)
    12.     {
    13.         playerReferenceToUseInServerRPC = player;
    14.         //thisAnimator = player.GetComponent<Animator>();
    15.         //thisAnimator.SetFloat("Attack", 0);
    16.         player.attackInput = false;
    17.     }
    18.  
    19.     public override void UpdateState(scr_PlayerStateManager player)
    20.     {
    21.         //if (player.attackInput)
    22.         //{
    23.         //    if (thisAnimator.GetFloat("Attack") > 0.5)
    24.         //    {
    25.         //        player.SwitchState(player.AttackingState);
    26.         //    }
    27.         //    thisAnimator.SetFloat("Attack", 1);
    28.         //}
    29.  
    30.         //thisAnimator.SetFloat("HorizontalAxis", player.moveInput.x);
    31.         //thisAnimator.SetFloat("VerticalAxis", player.moveInput.y);
    32.  
    33.     }
    34.  
    35.     public override void FixedUpdateState(scr_PlayerStateManager player)
    36.     {
    37.         if (player.IsLocalPlayer)
    38.         {
    39.             var movement = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
    40.             var newPosition = player.rb2d.position + player.speed * Time.fixedDeltaTime * movement;
    41.             player.rb2d.MovePosition(newPosition);
    42.  
    43.             if (NetworkManager.Singleton.IsServer)
    44.             {
    45.                 player.Position.Value = newPosition;
    46.             }
    47.             else
    48.             {
    49.                 PlayerMovementServerRpc(newPosition);
    50.             }
    51.         }
    52.         else
    53.         {
    54.             player.rb2d.MovePosition(player.Position.Value);
    55.         }
    56.     }
    57.  
    58.     [ServerRpc]
    59.     void PlayerMovementServerRpc(Vector2 posVector, ServerRpcParams rpcParams = default)
    60.     {
    61.         Debug.Log("(In ServerRPC Function) is server?" + NetworkManager.Singleton.IsServer);
    62.         playerReferenceToUseInServerRPC.Position.Value = posVector;
    63.         Debug.Log("can't see this because has error on previous line");
    64.     }
    65. }
    66.  
    This script is getting used in a state machine that passes in "this" as an argument.


    In the console I see the same two messages repeating

    (In ServerRPC Function) is server?False

    InvalidOperationException: Client is not allowed to write to this NetworkVariable
    Unity.Netcode.NetworkVariable`1[T].set_Value (T value) (at Library/PackageCache/com.unity.netcode.gameobjects@1.0.0-pre.7/Runtime/NetworkVariable/NetworkVariable.cs:104)
    scr_PlayerMovingState.PlayerMovementServerRpc (UnityEngine.Vector2 posVector, Unity.Netcode.ServerRpcParams rpcParams) (at Assets/Scripts/Player/scr_PlayerMovingState.cs:62)
    scr_PlayerMovingState.FixedUpdateState (scr_PlayerStateManager player) (at Assets/Scripts/Player/scr_PlayerMovingState.cs:49)
    scr_PlayerStateManager.FixedUpdate () (at Assets/Scripts/Player/scr_PlayerStateManager.cs:40)


    Anyone know how this could be possible?
     
  2. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    664
    The most likely cause is you're not deriving from NetworkBehaviour, try doing that in scr_PlayerBaseState.
     
  3. Ukutura

    Ukutura

    Joined:
    Jan 16, 2022
    Posts:
    10
    scr_PlayerBaseState is an abstract class that just has some empty functions

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public abstract class scr_PlayerBaseState
    5. {
    6.     public abstract void EnterState(scr_PlayerStateManager player);
    7.     public abstract void UpdateState(scr_PlayerStateManager player);
    8.     public abstract void FixedUpdateState(scr_PlayerStateManager player);
    9.     //void OnCollisionEnter();
    10.  
    11. }
    12.  
    My scr_PlayerStateManager is the one calling the functions, and it inherits from NetworkBehaviour

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Unity.Netcode;
    5. using UnityEngine.InputSystem;
    6.  
    7. public class scr_PlayerStateManager : NetworkBehaviour
    8. {
    9.     public float speed = 3f;
    10.    
    11.     public Rigidbody2D rb2d;
    12.     public bool attackInput;
    13.     public int attackID = -1;
    14.     public Vector2 moveInput = new Vector2(0,0);
    15.     public GameObject dot1; //a small orange dot for debugging
    16.  
    17.     public NetworkVariable<Vector2> Position = new NetworkVariable<Vector2>();
    18.  
    19.     public scr_PlayerBaseState currentState;
    20.     public scr_PlayerMovingState MovingState = new scr_PlayerMovingState();
    21.     public scr_PlayerAttackingState AttackingState = new scr_PlayerAttackingState();
    22.  
    23.     private void Awake()
    24.     {
    25.         rb2d = GetComponent<Rigidbody2D>();
    26.     }
    27.     private void Start()
    28.     {
    29.         currentState = MovingState;
    30.         currentState.EnterState(this);
    31.     }
    32.  
    33.     private void Update()
    34.     {
    35.         currentState.UpdateState(this);
    36.     }
    37.  
    38.     private void FixedUpdate()
    39.     {
    40.         currentState.FixedUpdateState(this);
    41.     }
    42.  
    43.     private void OnFire(InputValue value)
    44.     {
    45.         attackInput = true;
    46.         attackID = Random.Range(0, int.MaxValue);
    47.     }
    48.  
    49.     private void OnMove(InputValue value)
    50.     {
    51.         moveInput = value.Get<Vector2>();
    52.     }
    53.  
    54.     public void SwitchState(scr_PlayerBaseState state)
    55.     {
    56.         currentState = state;
    57.         state.EnterState(this);
    58.     }
    I agree that it seems like something like that is going on though. Any other ideas?
     
  4. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    664
    In that case you'll need to move the RPC call into scr_PlayerStateManager, the RPC function needs to be in the class derived from NetworkBehaviour. I could be wrong, but I wouldn't expect the way you have it set up to work.
     
    Ukutura likes this.
  5. Ukutura

    Ukutura

    Joined:
    Jan 16, 2022
    Posts:
    10
    I'll try that now, thanks
     
  6. Ukutura

    Ukutura

    Joined:
    Jan 16, 2022
    Posts:
    10
    You're a god, that seems to've done it, thank you so much.
     
    cerestorm likes this.