Search Unity

Question How to sync Instantiated GameObject on client or host for everyone?

Discussion in 'Netcode for GameObjects' started by luuqe, Apr 5, 2022.

  1. luuqe

    luuqe

    Joined:
    Jan 21, 2022
    Posts:
    11
    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using Cinemachine;
    6. using StarterAssets;
    7. using UnityEngine.InputSystem;
    8. using MLAPI;
    9. using MLAPI.Messaging;
    10. using MLAPI.NetworkedVar;
    11. using MLAPI.Spawning;
    12.  
    13. public class PlayerShootController : NetworkedBehaviour
    14. {
    15.     [SerializeField] private CinemachineVirtualCamera aimCamera;
    16.     [SerializeField] private CinemachineVirtualCamera followCamera;
    17.     [SerializeField] private float normalSensitivity = 1f;
    18.     [SerializeField] private float aimSensitivity = 0.5f;
    19.     [SerializeField] private float aimSprintSpeed = 2.5f;
    20.     [SerializeField] private LayerMask aimColliderLayerMask = new LayerMask();
    21.     [SerializeField] private Transform debugTransform;
    22.     [SerializeField] private Transform bulletTransform;
    23.     [SerializeField] private Transform spawnBulletPos;
    24.  
    25.     private NetworkedVarBool _shooting =
    26.         new NetworkedVarBool(new NetworkedVarSettings {WritePermission = NetworkedVarPermission.OwnerOnly}, false);
    27.  
    28.     private StarterAssetsInputs _inputs;
    29.     private ThirdPersonController _thirdPersonController;
    30.    
    31.     private void Awake()
    32.     {
    33.         _inputs = GetComponent<StarterAssetsInputs>();
    34.         _thirdPersonController = GetComponent<ThirdPersonController>();
    35.     }
    36.  
    37.     private void Update()
    38.     {
    39.         if (IsLocalPlayer)
    40.         {
    41.             _shooting.Value = _inputs.shoot;
    42.            
    43.             Vector3 mouseWorldPosition = Vector3.zero;
    44.             Vector2 screenCenter = new Vector2(Screen.width / 2f, Screen.height / 2f);
    45.             Ray ray = Camera.main.ScreenPointToRay(screenCenter);
    46.             Transform hitTransform = null;
    47.             if (Physics.Raycast(ray, out RaycastHit raycastHit, 999f))
    48.             {
    49.                 debugTransform.position = raycastHit.point;
    50.                 mouseWorldPosition = raycastHit.point;
    51.                 hitTransform = raycastHit.transform;
    52.             }
    53.            
    54.             if (_inputs.aim)
    55.             {
    56.                 followCamera.gameObject.SetActive(false);
    57.                 aimCamera.gameObject.SetActive(true);
    58.                 _thirdPersonController.SetSensitivity(aimSensitivity);
    59.  
    60.                 Vector3 worldAimTarget = mouseWorldPosition;
    61.                 worldAimTarget.y = transform.position.y;
    62.                 Vector3 aimDirection = (worldAimTarget - transform.position).normalized;
    63.  
    64.                 transform.forward = Vector3.Lerp(transform.forward, aimDirection, Time.deltaTime * 20f);
    65.                
    66.                 _thirdPersonController.SetRotationOnMove(false);
    67.                 _thirdPersonController.SetSprintSpeedOnAim(aimSprintSpeed);
    68.                
    69.             }
    70.             else
    71.             {
    72.                 followCamera.gameObject.SetActive(true);
    73.                 aimCamera.gameObject.SetActive(false);
    74.                
    75.                 _thirdPersonController.SetSensitivity(normalSensitivity);
    76.                 _thirdPersonController.SetRotationOnMove(true);
    77.                 _thirdPersonController.SetSprintSpeedOnAim(5.33f);
    78.             }
    79.  
    80.             if (_inputs.shoot && _shooting.Value)
    81.             {
    82.                 Debug.Log("Shooting");
    83.  
    84.                 InvokeServerRpc(ShootProjectileServerRpc, mouseWorldPosition);
    85.                
    86.                 _inputs.shoot = false;
    87.             }
    88.         }
    89.     }
    90.  
    91.     [ClientRPC]
    92.     private void ShootProjectileClientRpc(Vector3 mouseWorldPosition)
    93.     {
    94.         // ShootProjectileServerRpc(mouseWorldPosition);
    95.         // todo: handle spawned game object on clients also
    96.     }
    97.  
    98.     [ServerRPC]
    99.     private void ShootProjectileServerRpc(Vector3 mouseWorldPosition)
    100.     {
    101.         Vector3 aimDir = (mouseWorldPosition - spawnBulletPos.position).normalized;
    102.         Instantiate(bulletTransform, spawnBulletPos.position, Quaternion.LookRotation(aimDir, Vector3.up));
    103.         // go.GetComponent<NetworkedObject>().Spawn(); ??
    104.     }
    105. }
    106.  
    upload_2022-4-5_18-38-12.png

    So basically this code works only on host, i see spawned bullet, but on client i can only spawn it and cannot see it, because its only on server, so how can I sync? this bullet with clients?
     
  2. CosmoM

    CosmoM

    Joined:
    Oct 31, 2015
    Posts:
    204
    If you put a NetworkObject on the bullet and uncomment your last line, that should work.

    There are other ways to do it, for example what I do is send a ClientRpc to the clients to also spawn bullets, but take into the network delay to spawn them further along their flight path so the hits sync up better. But that also depends on how you handle e.g. hit registration, so pick whatever works for you.
     
  3. Draener

    Draener

    Joined:
    Dec 17, 2021
    Posts:
    7
    1. Instantiate(bulletTransform, spawnBulletPos.position, Quaternion.LookRotation(aimDir, Vector3.up));
    2. // go.GetComponent<NetworkedObject>().Spawn(); ??

      This is what you need to do.... your Instantiate call returns a game object..... you need to save that ... then get the network object and spawn it.

      So
      Code (CSharp):
      1. GameObject go = Instantiate(.......);
      2. go.GetComponent<NetworkedObject>().Spawn();
      You probably also want a network rigid body on your bullet, but it should work without it as well.
     
    Last edited: Apr 7, 2022