Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Only host is able to call serverrpc

Discussion in 'Netcode for GameObjects' started by cesar121321432, Jul 26, 2023.

  1. cesar121321432

    cesar121321432

    Joined:
    Jul 11, 2020
    Posts:
    20
    Hello, im trying to make a gun script, i have a smoke effect and muzzleflasheffect functions that are being called and are also both serverrpc:
    Code (CSharp):
    1.     [ServerRpc(RequireOwnership = false)]
    2.     public void SmokeGameobjectServerRpc()
    3.     {
    4.         GameObject go = Instantiate(smokegobj, shootpoint.transform.position, shootpoint.transform.rotation);
    5.         go.GetComponent<NetworkObject>().Spawn();
    6.    
    7.  
    8.  
    9.     }
    10.  
    11.  
    12.  
    13.  
    14.     [ServerRpc(RequireOwnership = false)]
    15.     public void MuzzleFlashGameobjectServerRpc()
    16.     {
    17.         GameObject go = Instantiate(muzzleflashGobj, shootpoint.transform.position, shootpoint.transform.rotation);
    18.         go.GetComponent<NetworkObject>().Spawn();
    19.  
    20.  
    21.     }

    and i also have a raycast script:

    Code (CSharp):
    1.     public void raycast_shoot()
    2.     {
    3.         RaycastHit hit;
    4.         if (Physics.Raycast(shootpoint.transform.position, shootpoint.transform.TransformDirection(Vector3.forward), out hit, Mathf.Infinity))
    5.         {
    6.             Debug.DrawRay(shootpoint.transform.position, shootpoint.transform.TransformDirection(Vector3.forward) * hit.distance, Color.yellow);
    7.             Debug.Log("Did Hit");
    8.             GameObject go = Instantiate(hitEffect, hit.point, Quaternion.LookRotation(hit.normal));
    9.             go.GetComponent<NetworkObject>().Spawn();
    10.         }
    11.         else
    12.         {
    13.             Debug.DrawRay(shootpoint.transform.position, shootpoint.transform.TransformDirection(Vector3.forward) * 1000, Color.white);
    14.             Debug.Log("Did not Hit");
    15.         }
    16.  
    17.     }


    The problem with these functions are that they are called when the host executes them, but NOT when the client does, so the client and the host can see the host shoot, but the host and client can't see the client shoot.

    help would be really appreciated
     
  2. lavagoatGG

    lavagoatGG

    Joined:
    Apr 16, 2022
    Posts:
    226
    Are they not being called or just the effect doesn't work? Maybe because the RPC's are executed on the server so the shootpoint isn't the client's one.
    Also, in your raycast script you are trying to spawn go but I think only the server is allowed to do that so the spawning should be in a serverRPC.
     
  3. cesar121321432

    cesar121321432

    Joined:
    Jul 11, 2020
    Posts:
    20
    'so the shootpoint isnt the clients one'

    they are being called with an event in an animation

    what do you mean by 'so the shootpoint isn't the client's one'
     
  4. Mj-Kkaya

    Mj-Kkaya

    Joined:
    Oct 10, 2017
    Posts:
    175
    Hi @cesar121321432
    I think you are not correctly understand of the NGO principle.
    You shared 2 ServerRpc methods but you didn't share where the exactly calling these methods?
    And when/where is calling the "raycast_shoot()"? And which game object?
    So you have a PlayerNetworkObject for each player and "raycast_shoot()" is calling from in the that script of NetworkObject?
    Please share more specific and detailed information.
     
  5. cesar121321432

    cesar121321432

    Joined:
    Jul 11, 2020
    Posts:
    20

    the 2 rpc methods are both being called with an event in a shoot animation

    the raycast_shoot() method is also being called in the animation as an event, its being called on the gun game object


    and this is the hierachy for the playercapsule:



    the playercapsule object is the player prefab, the gun is attached with the inventory to the maincamera and the gun has arms with ik, the shootpoint is inside the gun prefab and is at the end of the barrel

    i have a network object:
    -on the playercapsule
    -on all the effects

    example of effect:


    PlayerCapsule Player Prefab:







    Here are the script for the makarov:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using TMPro;
    4. using Unity.Mathematics;
    5. using Unity.Netcode;
    6. using UnityEngine;
    7.  
    8. public class Makarov : NetworkBehaviour
    9. {
    10.     public Animator anim;
    11.     public AudioSource src;
    12.     public AudioClip shoot_clip;
    13.  
    14.     public GameObject smokegobj;
    15.     public Transform gun;
    16.     public Vector3 gunaimPos;
    17.     public quaternion pivot;
    18.     public Transform player;
    19.     public float AimSpeed = 5;
    20.    
    21.     public Transform shootpoint;
    22.     public GameObject hitEffect;
    23.  
    24.     public GameObject muzzleflashGobj;
    25.     // Start is called before the first frame update
    26.     void Start()
    27.     {
    28.         if (!IsOwner) return;
    29.         gunaimPos = new Vector3(0.117f, 0.018f, 0.083f);
    30.         gameObject.GetComponent<NetworkObject>().Spawn();
    31.    
    32.     }
    33.  
    34.  
    35.     // Update is called once per frame
    36.     void Update()
    37.     {
    38.         if (!IsOwner) return;
    39.  
    40.         player.localRotation = Quaternion.Lerp(player.localRotation, pivot, AimSpeed * Time.deltaTime);
    41.         gun.localPosition = Vector3.Slerp(transform.localPosition, gunaimPos, AimSpeed * Time.deltaTime);
    42.         if (Input.GetMouseButtonDown(0))
    43.         {
    44.  
    45.             playAnim();
    46.  
    47.  
    48.  
    49.         }
    50.         if (Input.GetMouseButtonDown(1))
    51.  
    52.         {
    53.             if (IsOwner)
    54.             {
    55.                 gunaimPos = new Vector3(0.00400000019f, 0.209999993f, 0.166615874f);
    56.                 // gun.localPosition = new Vector3(0.002f, 0.134f, 0.083f);
    57.             }
    58.         }
    59.         if (Input.GetMouseButtonUp(1))
    60.         {
    61.             if (IsOwner)
    62.             {
    63.                 gunaimPos = new Vector3(0.117f, 0.018f, 0.083f);
    64.                 //gun.localPosition = new Vector3(0.117f, 0.018f, 0.083f);
    65.             }
    66.         }
    67.  
    68.     }
    69.    
    70.     public void playAnim() {
    71.         anim.Play("Makarov_Shoot");
    72.     }
    73.  
    74.     public void raycast_shoot()
    75.     {
    76.         RaycastHit hit;
    77.         if (Physics.Raycast(shootpoint.transform.position, shootpoint.transform.TransformDirection(Vector3.forward), out hit, Mathf.Infinity))
    78.         {
    79.             Debug.DrawRay(shootpoint.transform.position, shootpoint.transform.TransformDirection(Vector3.forward) * hit.distance, Color.yellow);
    80.             Debug.Log("Did Hit");
    81.             GameObject go = Instantiate(hitEffect, hit.point, Quaternion.LookRotation(hit.normal));
    82.             go.GetComponent<NetworkObject>().Spawn();
    83.         }
    84.         else
    85.         {
    86.             Debug.DrawRay(shootpoint.transform.position, shootpoint.transform.TransformDirection(Vector3.forward) * 1000, Color.white);
    87.             Debug.Log("Did not Hit");
    88.         }
    89.       //  gameObject.GetComponent<NetworkObject>().Spawn();
    90.     }
    91.  
    92.     public void shoot_sound()
    93.     {
    94.    
    95.  
    96.             src.PlayOneShot(shoot_clip);
    97.             //gameObject.GetComponent<NetworkObject>().Spawn();
    98.        
    99.  
    100.     }
    101.     [ServerRpc(RequireOwnership = false)]
    102.     public void SmokeGameobjectServerRpc()
    103.     {
    104.         GameObject go = Instantiate(smokegobj, shootpoint.transform.position, shootpoint.transform.rotation);
    105.         go.GetComponent<NetworkObject>().Spawn();
    106.      
    107.  
    108.  
    109.     }
    110.  
    111.  
    112.  
    113.  
    114.     [ServerRpc(RequireOwnership = false)]
    115.     public void MuzzleFlashGameobjectServerRpc()
    116.     {
    117.         GameObject go = Instantiate(muzzleflashGobj, shootpoint.transform.position, shootpoint.transform.rotation);
    118.         go.GetComponent<NetworkObject>().Spawn();
    119.    
    120.  
    121.     }
    122.  
    123.  
    124.  
    125. }
    126.  
    Hope this is enough info...
     
  6. Mj-Kkaya

    Mj-Kkaya

    Joined:
    Oct 10, 2017
    Posts:
    175
    Okay, these information are good.
    But, why you are call "spawn" method in "Start Method" of "Makarov" script?
    I think this isn't necessary because when PlayerCapsule is spawning "Makarov" will be also spawn. Because it is child object of PlayerCapsule.
    Code (CSharp):
    1.  void Start()
    2.     {
    3.         if (!IsOwner) return;
    4.         gunaimPos = new Vector3(0.117f, 0.018f, 0.083f);
    5.         gameObject.GetComponent<NetworkObject>().Spawn();
    6.  
    7.     }
    Actually I couldn't find the problem.
    I create similar hierarchy on my test project and it's work.
    I have a PlayerObject and added a child object then I try to trigger ServerRpc method and it works.
    Actually you can't add "NetworkObject" object to the sub objects of Parent object who has also has "NetworkObject". Unity giving this error:
    Spawning NetworkObjects with nested NetworkObjects is only supported for scene objects. Child NetworkObjects will not be spawned over the network!
    Is "PlayerCapsule" scene object?

    Would you add some log and share us please.
     
  7. cesar121321432

    cesar121321432

    Joined:
    Jul 11, 2020
    Posts:
    20

    Thank you so much for helping!

    the 'gameObject.GetComponent<NetworkObject>().Spawn();' method in start i didnt mean to put there so ill delete it.

    what do you mean with scene object, do you mean Player Prefab, because it is.
    or do you mean if it has an network object, because it does.

    again thank you, i am experienced with unity but just not with netcode at all, so the help is great!
     
  8. Mj-Kkaya

    Mj-Kkaya

    Joined:
    Oct 10, 2017
    Posts:
    175
    There are two types (Dynamic and In-Scene Placed) NetworkObjects.
    You can look at this documentation page.
    If I understood correctly, your PlayerCapsule is In-scene placed object. This means only one player can control this object at the same time.
    I am curious of your PlayerCapsule controlling. If your PlayerCapsule is In-scene object, how do you move this object for each player?
     
  9. Mj-Kkaya

    Mj-Kkaya

    Joined:
    Oct 10, 2017
    Posts:
    175
  10. cesar121321432

    cesar121321432

    Joined:
    Jul 11, 2020
    Posts:
    20
    my player is spawed with the player prefab method in the networkmanager

    here is the player script:
    Code (CSharp):
    1.  
    2. using System;
    3. using Unity.Netcode;
    4. using UnityEngine;
    5.  
    6. public class PlayerController : NetworkBehaviour
    7. {
    8.  
    9.     //Assingables
    10.     public Transform playerCam;
    11.     public Transform orientation;
    12.  
    13.     //Other
    14.     private Rigidbody rb;
    15.  
    16.     //Rotation and look
    17.     private float xRotation;
    18.     private float sensitivity = 50f;
    19.     private float sensMultiplier = 1f;
    20.  
    21.     //Movement
    22.     public float moveSpeed = 4500;
    23.     public float maxSpeed = 20;
    24.     public bool grounded;
    25.     public LayerMask whatIsGround;
    26.  
    27.     public float counterMovement = 0.175f;
    28.     private float threshold = 0.01f;
    29.     public float maxSlopeAngle = 35f;
    30.  
    31.     //Crouch & Slide
    32.     private Vector3 crouchScale = new Vector3(1, 0.5f, 1);
    33.     private Vector3 playerScale;
    34.     public float slideForce = 400;
    35.     public float slideCounterMovement = 0.2f;
    36.  
    37.     //Jumping
    38.     private bool readyToJump = true;
    39.     private float jumpCooldown = 0.25f;
    40.     public float jumpForce = 550f;
    41.  
    42.     //Input
    43.     float x, y;
    44.     bool jumping, sprinting, crouching;
    45.  
    46.     //Sliding
    47.     private Vector3 normalVector = Vector3.up;
    48.     private Vector3 wallNormalVector;
    49.  
    50.     void Awake()
    51.     {
    52.         rb = GetComponent<Rigidbody>();
    53.     }
    54.  
    55.     void Start()
    56.     {
    57.         playerScale = transform.localScale;
    58.         Cursor.lockState = CursorLockMode.Locked;
    59.         Cursor.visible = false;
    60.     }
    61.  
    62.  
    63.     private void FixedUpdate()
    64.     {
    65.         Movement();
    66.     }
    67.     public override void OnNetworkSpawn()
    68.     {
    69.         if (!IsOwner) { Destroy(this); }
    70.     }
    71.     private void Update()
    72.     {
    73.         MyInput();
    74.         Look();
    75.     }
    76.  
    77.     /// <summary>
    78.     /// Find user input. Should put this in its own class but im lazy
    79.     /// </summary>
    80.     private void MyInput()
    81.     {
    82.         x = Input.GetAxisRaw("Horizontal");
    83.         y = Input.GetAxisRaw("Vertical");
    84.         jumping = Input.GetButton("Jump");
    85.         crouching = Input.GetKey(KeyCode.LeftControl);
    86.  
    87.         //Crouching
    88.         if (Input.GetKeyDown(KeyCode.LeftControl))
    89.             StartCrouch();
    90.         if (Input.GetKeyUp(KeyCode.LeftControl))
    91.             StopCrouch();
    92.     }
    93.  
    94.     private void StartCrouch()
    95.     {
    96.         transform.localScale = crouchScale;
    97.         transform.position = new Vector3(transform.position.x, transform.position.y - 0.5f, transform.position.z);
    98.         if (rb.velocity.magnitude > 0.5f)
    99.         {
    100.             if (grounded)
    101.             {
    102.                 rb.AddForce(orientation.transform.forward * slideForce);
    103.             }
    104.         }
    105.     }
    106.  
    107.     private void StopCrouch()
    108.     {
    109.         transform.localScale = playerScale;
    110.         transform.position = new Vector3(transform.position.x, transform.position.y + 0.5f, transform.position.z);
    111.     }
    112.  
    113.     private void Movement()
    114.     {
    115.         //Extra gravity
    116.         rb.AddForce(Vector3.down * Time.deltaTime * 10);
    117.  
    118.         //Find actual velocity relative to where player is looking
    119.         Vector2 mag = FindVelRelativeToLook();
    120.         float xMag = mag.x, yMag = mag.y;
    121.  
    122.         //Counteract sliding and sloppy movement
    123.         CounterMovement(x, y, mag);
    124.  
    125.         //If holding jump && ready to jump, then jump
    126.         if (readyToJump && jumping) Jump();
    127.  
    128.         //Set max speed
    129.         float maxSpeed = this.maxSpeed;
    130.  
    131.         //If sliding down a ramp, add force down so player stays grounded and also builds speed
    132.         if (crouching && grounded && readyToJump)
    133.         {
    134.             rb.AddForce(Vector3.down * Time.deltaTime * 3000);
    135.             return;
    136.         }
    137.  
    138.         //If speed is larger than maxspeed, cancel out the input so you don't go over max speed
    139.         if (x > 0 && xMag > maxSpeed) x = 0;
    140.         if (x < 0 && xMag < -maxSpeed) x = 0;
    141.         if (y > 0 && yMag > maxSpeed) y = 0;
    142.         if (y < 0 && yMag < -maxSpeed) y = 0;
    143.  
    144.         //Some multipliers
    145.         float multiplier = 1f, multiplierV = 1f;
    146.  
    147.         // Movement in air
    148.         if (!grounded)
    149.         {
    150.             multiplier = 0.5f;
    151.             multiplierV = 0.5f;
    152.         }
    153.  
    154.         // Movement while sliding
    155.         if (grounded && crouching) multiplierV = 0f;
    156.  
    157.         //Apply forces to move player
    158.         rb.AddForce(orientation.transform.forward * y * moveSpeed * Time.deltaTime * multiplier * multiplierV);
    159.         rb.AddForce(orientation.transform.right * x * moveSpeed * Time.deltaTime * multiplier);
    160.     }
    161.  
    162.     private void Jump()
    163.     {
    164.         if (grounded && readyToJump)
    165.         {
    166.             readyToJump = false;
    167.  
    168.             //Add jump forces
    169.             rb.AddForce(Vector2.up * jumpForce * 1.5f);
    170.             rb.AddForce(normalVector * jumpForce * 0.5f);
    171.  
    172.             //If jumping while falling, reset y velocity.
    173.             Vector3 vel = rb.velocity;
    174.             if (rb.velocity.y < 0.5f)
    175.                 rb.velocity = new Vector3(vel.x, 0, vel.z);
    176.             else if (rb.velocity.y > 0)
    177.                 rb.velocity = new Vector3(vel.x, vel.y / 2, vel.z);
    178.  
    179.             Invoke(nameof(ResetJump), jumpCooldown);
    180.         }
    181.     }
    182.  
    183.     private void ResetJump()
    184.     {
    185.         readyToJump = true;
    186.     }
    187.  
    188.     private float desiredX;
    189.     private void Look()
    190.     {
    191.         float mouseX = Input.GetAxis("Mouse X") * sensitivity * Time.fixedDeltaTime * sensMultiplier;
    192.         float mouseY = Input.GetAxis("Mouse Y") * sensitivity * Time.fixedDeltaTime * sensMultiplier;
    193.  
    194.         //Find current look rotation
    195.         Vector3 rot = playerCam.transform.localRotation.eulerAngles;
    196.         desiredX = rot.y + mouseX;
    197.  
    198.         //Rotate, and also make sure we dont over- or under-rotate.
    199.         xRotation -= mouseY;
    200.         xRotation = Mathf.Clamp(xRotation, -90f, 90f);
    201.  
    202.         //Perform the rotations
    203.         playerCam.transform.localRotation = Quaternion.Euler(xRotation, desiredX, 0);
    204.         orientation.transform.localRotation = Quaternion.Euler(0, desiredX, 0);
    205.     }
    206.  
    207.     private void CounterMovement(float x, float y, Vector2 mag)
    208.     {
    209.         if (!grounded || jumping) return;
    210.  
    211.         //Slow down sliding
    212.         if (crouching)
    213.         {
    214.             rb.AddForce(moveSpeed * Time.deltaTime * -rb.velocity.normalized * slideCounterMovement);
    215.             return;
    216.         }
    217.  
    218.         //Counter movement
    219.         if (Math.Abs(mag.x) > threshold && Math.Abs(x) < 0.05f || (mag.x < -threshold && x > 0) || (mag.x > threshold && x < 0))
    220.         {
    221.             rb.AddForce(moveSpeed * orientation.transform.right * Time.deltaTime * -mag.x * counterMovement);
    222.         }
    223.         if (Math.Abs(mag.y) > threshold && Math.Abs(y) < 0.05f || (mag.y < -threshold && y > 0) || (mag.y > threshold && y < 0))
    224.         {
    225.             rb.AddForce(moveSpeed * orientation.transform.forward * Time.deltaTime * -mag.y * counterMovement);
    226.         }
    227.  
    228.         //Limit diagonal running. This will also cause a full stop if sliding fast and un-crouching, so not optimal.
    229.         if (Mathf.Sqrt((Mathf.Pow(rb.velocity.x, 2) + Mathf.Pow(rb.velocity.z, 2))) > maxSpeed)
    230.         {
    231.             float fallspeed = rb.velocity.y;
    232.             Vector3 n = rb.velocity.normalized * maxSpeed;
    233.             rb.velocity = new Vector3(n.x, fallspeed, n.z);
    234.         }
    235.     }
    236.  
    237.     /// <summary>
    238.     /// Find the velocity relative to where the player is looking
    239.     /// Useful for vectors calculations regarding movement and limiting movement
    240.     /// </summary>
    241.     /// <returns></returns>
    242.     public Vector2 FindVelRelativeToLook()
    243.     {
    244.         float lookAngle = orientation.transform.eulerAngles.y;
    245.         float moveAngle = Mathf.Atan2(rb.velocity.x, rb.velocity.z) * Mathf.Rad2Deg;
    246.  
    247.         float u = Mathf.DeltaAngle(lookAngle, moveAngle);
    248.         float v = 90 - u;
    249.  
    250.         float magnitue = rb.velocity.magnitude;
    251.         float yMag = magnitue * Mathf.Cos(u * Mathf.Deg2Rad);
    252.         float xMag = magnitue * Mathf.Cos(v * Mathf.Deg2Rad);
    253.  
    254.         return new Vector2(xMag, yMag);
    255.     }
    256.  
    257.     private bool IsFloor(Vector3 v)
    258.     {
    259.         float angle = Vector3.Angle(Vector3.up, v);
    260.         return angle < maxSlopeAngle;
    261.     }
    262.  
    263.     private bool cancellingGrounded;
    264.  
    265.     /// <summary>
    266.     /// Handle ground detection
    267.     /// </summary>
    268.     private void OnCollisionStay(Collision other)
    269.     {
    270.         //Make sure we are only checking for walkable layers
    271.         int layer = other.gameObject.layer;
    272.         if (whatIsGround != (whatIsGround | (1 << layer))) return;
    273.  
    274.         //Iterate through every collision in a physics update
    275.         for (int i = 0; i < other.contactCount; i++)
    276.         {
    277.             Vector3 normal = other.contacts[i].normal;
    278.             //FLOOR
    279.             if (IsFloor(normal))
    280.             {
    281.                 grounded = true;
    282.                 cancellingGrounded = false;
    283.                 normalVector = normal;
    284.                 CancelInvoke(nameof(StopGrounded));
    285.             }
    286.         }
    287.  
    288.         //Invoke ground/wall cancel, since we can't check normals with CollisionExit
    289.         float delay = 3f;
    290.         if (!cancellingGrounded)
    291.         {
    292.             cancellingGrounded = true;
    293.             Invoke(nameof(StopGrounded), Time.deltaTime * delay);
    294.         }
    295.     }
    296.  
    297.     private void StopGrounded()
    298.     {
    299.         grounded = false;
    300.     }
    301.  
    302. }
     
  11. Mj-Kkaya

    Mj-Kkaya

    Joined:
    Oct 10, 2017
    Posts:
    175
    @cesar121321432,
    I want to be clear to you. I think, you should start to read/learn beginning of the NGO because, PlayerController script has many wrong and unnecessary code.
    For example:
    • Why OnNetworkSpawn method like this: if (!IsOwner) { Destroy(this); } If you do this you destroy other player's PlayerPrefab object. Actually, probably this line gives authority error.
    • You have to add "if (!IsOwner) return;" line to the "Movement()", "MyInput()" and "Look()" methods because, many "PlayerPrefab" objects will be in the scene.
    Have a nice day.
     
  12. cesar121321432

    cesar121321432

    Joined:
    Jul 11, 2020
    Posts:
    20
    im sorry but how does this apply to the question???