Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Question Owner has control over all spawned playerObjects

Discussion in 'Netcode for GameObjects' started by tdfbourne, Aug 13, 2023.

  1. tdfbourne

    tdfbourne

    Joined:
    May 3, 2021
    Posts:
    3
    Hi all, I am kind of running out of idea's. I'm interacting with netcode and ServerRpc for the first time. I decided to use ServerRpc for spawning my playerPrefabs as I want to potentially have different prefabs for each player, as well as place them in specific locations of the map. But for some reason, whenever a client connects, it is unable to control its own playerPrefab and the host controls them all.

    on top of this, even with having all the prefabs within the networkPrefabs of the network manager, and having network transforms on them too, they only seem to move on the host and not on the clients. Would anyone be able to give me any insight into this?

    The code for the spawning of players is:

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3. using Unity.Netcode;
    4.  
    5. public class PlayerSpawns : NetworkBehaviour
    6. {
    7.     public GameObject playerPrefab;
    8.  
    9.     // List to store used spawn points
    10.     private List<Transform> usedSpawnPoints = new List<Transform>();
    11.  
    12.  
    13.     public override void OnNetworkSpawn()
    14.     {
    15.         base.OnNetworkSpawn();
    16.         PlayerSpawnsServerRpc();
    17.         // Find an available spawn point
    18.     }
    19.  
    20.     [ServerRpc(RequireOwnership = false)]
    21.     private void PlayerSpawnsServerRpc()
    22.     {
    23.         if (!IsOwner) Destroy(this);
    24.         ulong clientId = OwnerClientId;
    25.         Transform spawnPoint = GetAvailableSpawnPoint();
    26.         if (spawnPoint != null)
    27.         {
    28.             // Spawn the specified prefab as a player object at the selected spawn point
    29.             NetworkObject spawnedObject = Instantiate(playerPrefab, spawnPoint.position, spawnPoint.rotation).GetComponent<NetworkObject>();
    30.             spawnedObject.SpawnAsPlayerObject(clientId);
    31.  
    32.             // Mark the spawn point as used
    33.             usedSpawnPoints.Add(spawnPoint);
    34.         }
    35.     }
    36.  
    37.  
    38.     private Transform GetAvailableSpawnPoint()
    39.     {
    40.         Transform[] spawnPoints = transform.GetComponentsInChildren<Transform>();
    41.         List<Transform> availableSpawnPoints = new List<Transform>();
    42.  
    43.         foreach (Transform spawnPoint in spawnPoints)
    44.         {
    45.             if (spawnPoint != transform && !usedSpawnPoints.Contains(spawnPoint))
    46.             {
    47.                 availableSpawnPoints.Add(spawnPoint);
    48.             }
    49.         }
    50.  
    51.         if (availableSpawnPoints.Count > 0)
    52.         {
    53.             int randomIndex = UnityEngine.Random.Range(0, availableSpawnPoints.Count);
    54.             return availableSpawnPoints[randomIndex];
    55.         }
    56.  
    57.         return null;
    58.     }
    59. }
    And the code I'm using for player movement is:

    Code (CSharp):
    1. using UnityEngine;
    2. using Unity.Netcode;
    3.  
    4. public class PlayerMovement : NetworkBehaviour
    5. {
    6.     public tankValues tankData;
    7.     private float movementSpeed;
    8.     private float turnSpeed;
    9.     private Rigidbody rb;
    10.  
    11.     private void Start()
    12.     {
    13.         rb = GetComponent<Rigidbody>();
    14.         movementSpeed = tankData.movementSpeed;
    15.         turnSpeed = tankData.tankRotationSpeed;
    16.     }
    17.  
    18.     private void FixedUpdate()
    19.     {
    20.         // Only allow the owner to update movement
    21.         if (!IsLocalPlayer)
    22.             return;
    23.  
    24.         float moveInput = Input.GetAxis("Vertical");
    25.         float turnInput = Input.GetAxis("Horizontal");
    26.  
    27.         Vector3 movement = transform.forward * moveInput * movementSpeed * Time.fixedDeltaTime;
    28.         rb.MovePosition(rb.position + movement);
    29.  
    30.         float turn = turnInput * turnSpeed * Time.fixedDeltaTime;
    31.         Quaternion turnRotation = Quaternion.Euler(0f, turn, 0f);
    32.         rb.MoveRotation(rb.rotation * turnRotation);
    33.     }
    34. }
    35.  
     
  2. Mj-Kkaya

    Mj-Kkaya

    Joined:
    Oct 10, 2017
    Posts:
    188
    Hi,
    What is "PlayerSpawns" object? Is this Scene-object?
    If it is scene-object the owner is Host.
    And "PlayerSpawnsServerRpc()" trigger only host side. So, "ulong clientId = OwnerClientId;" line returns always HostId.
     
  3. tdfbourne

    tdfbourne

    Joined:
    May 3, 2021
    Posts:
    3
    The PlayerSpawns script is within the scene yeah, it's attached to a spawnfield object that contains 4 different gameobjects with spawn locations.

    Aha, okay, so how would I make it so that it does it for both server and client side? I want it to obviously be separate, since the host is technically just a client whos hosting the server, so each client can control their own playerPrefab..

    Also, any idea on why it's not updating the transforms for the client?
     
  4. Mj-Kkaya

    Mj-Kkaya

    Joined:
    Oct 10, 2017
    Posts:
    188
    I can give some simple suggestion.
    Listen the "NetworkManager.Singleton.OnClientConnectedCallback" callback for connected clients on Host side. Then Instantiate PlayerObject with "SpawnAsPlayerObject" method.