Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Changing from server authority to local authority at runtime in NetworkIdentity?

Discussion in 'Multiplayer' started by Sir-Spunky, Oct 28, 2017.

  1. Sir-Spunky

    Sir-Spunky

    Joined:
    Apr 7, 2013
    Posts:
    132
    Hi,

    I'm building an RPG, and I want to use the same prefab for NPC characters and player characters. My idea was to spawn all characters with server authority, and then give authority to a specific player, so that they "take control" over a character. I do this by first spawning an invisible Player object, which in turn tells the server to spawn the character prefab and then tries to give control over it to the player. However, this doesn't seem to work.

    When I try methods such as NetworkIdentity.AssignClientAuthority() or even NetworkServer.SpawnWithClientAuthority() on the character prefab that doesn't have local authority, I just get an error message: "AssignClientAuthority can only be used for NetworkIdentity component with LocalPlayerAuthority". I've tried to set NetworkIdentity.localPlayerAuthority = true at runtime after instantiating the prefab, but this doesn't seem to help.

    Because I attach the rigidbody to the character prefab, I have to have the NetworkTransform there, and so need to have the NetworkIdentity there as well. If I set localPlayerAuthority to true beforehand in the prefab itself, it works fine. But I assume that means I can't use the same prefab for spawning NPC:s with server authority.

    Any ideas how to solve this, without needing duplicate prefabs for player characters and NPC:s? I'm not sure how nesting NetworkIdentities work, if I could utilize that, or I'm thinking I could create a generic character object through code rather than using a prefab for the initial spawn.

    Edit: Another idea I just got is to create a super barebone "character" object, that basically just contains a rigidbody, NetworkTransform and NetworkIdentity. Or rather two such prefabs, one with local and one with server authority. Then after spawning that, I could make them spawn the character models and colliders dynamically on all clients.

    However, it would still be very useful to be able to switch between server authority and local authority dynamically, so that you could design in-game spells that let you take control over an NPC, without having to respawn the character object from scratch.
     
    Last edited: Oct 28, 2017
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,825
    In the game I'm making I took a slightly different approach by leaving the player's character with server authority. I spawn the Player object in as an object with just scripts on it, and the server side version (after verifying a character for this player doesn't already exist in the game world) then instantiates and spawns in the correct character for the player and stores a reference to it to control it (in my case a sailing ship the player controls).

    The controls for moving the character or other actions are taken from the user on the Player object itself, which sends commands to the server version of the player object. On the server the player object then tells the character object to do whatever the user wanted, all through the reference originally stored for it.

    NPC versions of the characters are instantiated and spawned on the server with an NPC spawn script, which just calls an extra method on them so the AI script on the character knows it is in control instead of a player. Basically just setting an IsAIControlled = true and a little other house keeping, otherwise the AI script does nothing. Same prefab for both player controlled and AI controlled.

    I can't say if this is a optimal solution, but it has been working for me just fine so far. Its a slow paced game where the user doesn't really need to see immediate response from the character, which might not work for your situation if your game is faster paced.
     
    Last edited: Oct 31, 2017
  3. Sir-Spunky

    Sir-Spunky

    Joined:
    Apr 7, 2013
    Posts:
    132
    Thanks for sharing! It's great to hear how others have solved this. Like you say, there might be a slight delay in input response if it doesn't make use of local player authority, but you're right that it might not be an issue in a slow-paced game.

    I never really tried complete server authority, but I finally came up with a solution which is good enough for me for the time being:

    I basically have one prefab for "Player" and one for "NPC". They contain no character model or data, but each have a Network Identity, Network Transform and Rigidbody component. Only the Player prefab has "local play authority" checked. They also have a script attached, which in its Start method instantiates (not spawns) a third prefab called "Character Model" as a child. This third prefab contains the actual model and bones of the character, as well as its colliders. Because it's run in the Start method, all clients automatically create this prefab as soon as the parent prefab is spawned, so that the character model becomes visible to everyone.

    This way, I can use the same character prefab for both players and npc:s, and I could also put additional data on this prefab such as how fast this character type is allowed to move, while still having local player authority for player characters. The key was to separate the rigidbody from the colliders, because I had to have the rigidbody together with the Network Transform/Network Identity component. This works because a parent rigidbody seems to govern over child colliders, even over the network.

    This is the solution I'm using right now, I have no idea if it'll work in the long run. :)