NotServerException: Only the server can find player objects from other clients

I’m making a game about delivering orders and I wrote a code that when a certain player delivers a wrong order or an order that is not requested it should enable a certain particle system only on that player (that particle sys is part of the player game object but it is disabled at the start) so it works fine for the clients he delivers a wrong order and it shows the particle sys on the client character you can see it both from the view of the client and the server but when the server/host delivers a wrong order it shows the particle sys on the server/host character only from the side/view of the server/host and the client can’t even see it on the character that belongs to the server/host and it gives an error in the debug of the client it says (NotServerException: Only the server can find player objects from other clients. Unity.Netcode.NetworkSpawnManager.GetPlayerNetworkObject).

This code is what I have tried and it throws the error above:

[ServerRpc(RequireOwnership = false)]
    private void NotifyWrongOrderDeliveryServerRpc(ulong playerId)
    {
        Debug.Log("Server notifying clients about wrong order delivered by player with ID: " + playerId);
        RpcClientShowDizzyEffectClientRpc(playerId);
    }

    [ClientRpc]
private void RpcClientShowDizzyEffectClientRpc(ulong playerId)
{
    Debug.Log("Client received notification about wrong order delivered by player with ID: " + playerId);
   
    // Request the player object from the server using the player ID
    NetworkObject playerObject = NetworkManager.Singleton.SpawnManager.GetPlayerNetworkObject(playerId);
    if (playerObject != null)
    {
        Player player = playerObject.GetComponent<Player>();
        if (player != null)
        {
            Debug.Log("Showing Dizzy effect locally for player with ID: " + playerId);
            player.StartCoroutine(player.ShowDizzyEffectLocally());
        }
        else
        {
            Debug.LogError("Player component not found on the player object.");
        }
    }
    else
    {
        Debug.LogError("Player object not found for player with ID: " + playerId);
    }
}

     // Method to deliver wrong order, called when wrong order is detected
    private void DeliverWrongOrder(ulong playerId)
    {
        // Logic to handle wrong order delivery...
        Debug.Log("Player with ID " + playerId + " delivered the wrong order.");

        // Notify all clients about the wrong order delivery
        NotifyWrongOrderDeliveryServerRpc(playerId);
    }

    // Method to detect wrong order and deliver it
    private void DetectAndDeliverWrongOrder()
    {
        // Logic to detect wrong order and extract the player ID

        // For demonstration purposes, let's assume you have access to the player ID here
        ulong wrongOrderPlayerId = ExtractPlayerId();

        // Call the method to deliver wrong order with the extracted player ID
        DeliverWrongOrder(wrongOrderPlayerId);
    }

    // Method to extract player ID (replace this with your actual logic)
    private ulong ExtractPlayerId()
    {
        // Example: Extract player ID from a networked object
        NetworkObject playerObject = GetPlayerObject();
        if (playerObject != null)
        {
            return playerObject.OwnerClientId;
        }
        else
        {
            // Handle the case where player object is not found
            Debug.LogError("Player object not found.");
            return NetworkManager.Singleton.LocalClientId; // Or return a default value
        }
    }

    // Example method to get player object (replace this with your actual logic)
    private NetworkObject GetPlayerObject()
    {
        // Example: Get player object from NetworkSpawnManager
        return NetworkManager.Singleton?.SpawnManager?.GetPlayerNetworkObject(NetworkManager.Singleton.LocalClientId);
    }

The line the error message points to has a statement that can only be run on the server. You need to ensure this is run only on the server, perhaps you need to send an RPC so the server runs this statement on behalf of the client.

Okay, so you are saying that this line that is conflicting with the clients?

    NetworkObject playerObject = NetworkManager.Singleton.SpawnManager.GetPlayerNetworkObject(playerId);

But how do I call that in the server and still pass the result to the clients?
I’m sorry I’m still a beginner in the field and I’m doing a side project. It’s more of a hobby to learn something new.

I have also tried this but it gives this error (RpcClientShowDizzyEffectClientRpc - Don’t know how to serialize NetworkObject).

[ServerRpc(RequireOwnership = false)]
    private void NotifyWrongOrderDeliveryServerRpc(ulong playerId)
    {
        Debug.Log("Server notifying clients about wrong order delivered by player with ID: " + playerId);
       
            NetworkObject playerObject = NetworkManager.Singleton.SpawnManager.GetPlayerNetworkObject(playerId);
RpcClientShowDizzyEffectClientRpc(playerObject);
    }

    [ClientRpc]
private void RpcClientShowDizzyEffectClientRpc(NetworkObject playerObject)
{
    //Debug.Log("Client received notification about wrong order delivered by player with ID: " + playerId);
   
    // Request the player object from the server using the player ID
    if (playerObject != null)
    {
        Player player = playerObject.GetComponent<Player>();
        if (player != null)
        {
       //     Debug.Log("Showing Dizzy effect locally for player with ID: " + playerId);
            player.StartCoroutine(player.ShowDizzyEffectLocally());
        }
        else
        {
            Debug.LogError("Player component not found on the player object.");
        }
    }
    else
    {
      //  Debug.LogError("Player object not found for player with ID: " + playerId);
    }
}

Replace NetworkObject with NetworkObjectReference, or just send the ulong NetworkObjectId and look it up in SpawnManager.

You can also replace GetPlayerNetworkObject by a simply lookup of the playerId in the SpawnedObjects list. I assume the players are also included in that list.

I completely removed the idea of requesting a change to be made for the host player character from the client to the server on the instance of the client. The solution was to avoid accessing anything of any player model (not just the host/server) as the client I just ask the server to send the position and ID of the player and then I spawn the effect as a child so it’s following the player. that way the effect is dynamically spawned and added as a child so that the clients and server can see when someone delivers, for example, a wrong order the effect appears on the player who did it so all players will see that effect on that specific player. Thanks @CodeSmile for guiding me.

1 Like