Search Unity

Using multiple player prefabs with the network manager?

Discussion in 'Multiplayer' started by khos, Oct 31, 2016.

  1. khos

    khos

    Joined:
    May 10, 2016
    Posts:
    1,490
    Hi,

    I would like to ask for some advice, I have been searching and find some posts about this but am not sure how to approach this yet.
    How can I set individual player Prefabs to client with the NetworkManger?
    I have more than one player prefab to choose from, but the network manager only allows for one player prefab..

    Threads like this https://forum.unity3d.com/threads/h...ent-in-the-networkmanger.348337/#post-2256378
    show some code, but I am not sure where to use the method:
    public override void OnServerAddPlayer

    Can I add that to any object in the same scene as the networkmanager? How should I use the override function/method?

    Thanks for any help on this.
     
  2. IAMBATMAN

    IAMBATMAN

    Joined:
    Aug 14, 2015
    Posts:
    272
    Hello, I recently did this with the help of this thread https://forum.unity3d.com/threads/unet-spawning-different-player-prefabs-solved.387747/

    I used this script

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Networking;
    3. using UnityEngine.Networking.NetworkSystem;
    4.  
    5. public class NetworkCustom : NetworkManager
    6. {
    7.  
    8.     public int chosenCharacter = 0;
    9.     public GameObject[] characters;
    10.  
    11.     //subclass for sending network messages
    12.     public class NetworkMessage : MessageBase
    13.     {
    14.         public int chosenClass;
    15.     }
    16.  
    17.     public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId, NetworkReader extraMessageReader)
    18.     {
    19.         NetworkMessage message = extraMessageReader.ReadMessage<NetworkMessage>();
    20.         int selectedClass = message.chosenClass;
    21.         Debug.Log("server add with message " + selectedClass);
    22.  
    23.         GameObject player;
    24.         Transform startPos = GetStartPosition();
    25.  
    26.         if(startPos != null)
    27.         {
    28.             player = Instantiate(characters[chosenCharacter], startPos.position,startPos.rotation)as GameObject;
    29.         }
    30.         else
    31.         {
    32.             player = Instantiate(characters[chosenCharacter], Vector3.zero, Quaternion.identity) as GameObject;
    33.  
    34.         }
    35.  
    36.         NetworkServer.AddPlayerForConnection(conn, player, playerControllerId);
    37.  
    38.     }
    39.  
    40.     public override void OnClientConnect(NetworkConnection conn)
    41.     {
    42.         NetworkMessage test = new NetworkMessage();
    43.         test.chosenClass = chosenCharacter;
    44.  
    45.         ClientScene.AddPlayer(conn, 0, test);
    46.     }
    47.  
    48.  
    49.     public override void OnClientSceneChanged(NetworkConnection conn)
    50.     {
    51.         //base.OnClientSceneChanged(conn);
    52.     }
    53.  
    54.     public void btn1()
    55.     {
    56.         chosenCharacter = 0;
    57.     }
    58.  
    59.     public void btn2()
    60.     {
    61.         chosenCharacter = 1;
    62.     }
    63. }
    64.  
    And on the networkmanager there's a field called "Script" just drag this script in there.
    Then add all you player prefabs to the characters field, the int chosenCharacter is the index for your characters.

    Then I made this quick script

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.Networking;
    4.  
    5. public class ChooseHero : MonoBehaviour {
    6.  
    7.     public GameObject characterSelect;
    8.  
    9.     public void PickHero(int hero)
    10.     {
    11.         NetworkManager.singleton.GetComponent<NetworkCustom>().chosenCharacter = hero;
    12.         characterSelect.SetActive(false);
    13.     }
    14. }
    15.  
    So that I could use unity's buttons to pick my character. I added this script to an empty object that I called "Game Manager"

    This lets you pick your character before you join a game. IMPORTANT Make sure to register your player prefabs with the networkmanager.
     
  3. khos

    khos

    Joined:
    May 10, 2016
    Posts:
    1,490

    WOW, Many thanks for your help with this, just what I wanted to understand. How can a network session be ended if using the custom script, i.e. the networkmanager persists over scenes, how can that be stopped (at end of level/gamescene)? is StopServer()?
    Thanks again for your help and sample script, much appreciated.
     
  4. IAMBATMAN

    IAMBATMAN

    Joined:
    Aug 14, 2015
    Posts:
    272
  5. khos

    khos

    Joined:
    May 10, 2016
    Posts:
    1,490
    Thanks, I thought it might be something like that.
    If I may ask another question about the code you kindly shared, do you see any problem if different clients choose different playerprefabs when joining, that to my mind should work, would you agree?
     
  6. IAMBATMAN

    IAMBATMAN

    Joined:
    Aug 14, 2015
    Posts:
    272
    Yes, It works for me when choosing different playerprefabs on different players.
     
    sheezu likes this.
  7. khos

    khos

    Joined:
    May 10, 2016
    Posts:
    1,490
    Hi, I'd like to ask what your approach would be for debugging an issue, in this scenario: server starts with player1 selected prefab, then clients join that server with other selected prefab2, but the prefab2 is not seen, only prefab1, why would that occur? it's as if only ever prefab1 can be used..
    E.g. try setting Debug.Log("text"); in various places?
    Thanks for any input on this.
     
  8. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    The strategy to adopt in these situations (and in general) is to say that the player prefab is a general-purpose "Player Manager" object, and not the player's character itself. Then, the server can give the PlayerManager any character to control
     
  9. khos

    khos

    Joined:
    May 10, 2016
    Posts:
    1,490
    Hi, thanks for your reply, I am not sure I understand where you write " is a general-purpose "Player Manager" object", how is that done? What code should be used for this?
     
  10. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Imagine you make a "PlayerManager" class that holds the player's score, name, etc.... and has a reference to its controlled character.

    Now if you want each player to have a different character for example, you can say in the NetworkManager that the player prefab is the PlayerManager, and then make sure that the NetworkManager spawns different characters and assigns their control/authority to their respective PlayerManager

    I use a structure like this even when I don't need every player to have a different prefab. It just seems more elegant/well-structured to me
     
  11. khos

    khos

    Joined:
    May 10, 2016
    Posts:
    1,490
    Thanks for your reply,
    So is it important that the network manager spawns the plsyer object? Or in your playermanager class would you have code such as:
    NetworkManager.singleton.GetComponent<NetworkCustom>().chosenCharacter = hero;
    characterSelect.SetActive(false);

    Thanks, It is a bit confusing to know what to do here exactly, hopefully you can provide more input.
     
  12. eating2016

    eating2016

    Joined:
    Aug 1, 2016
    Posts:
    5
    Hi, many thanks for sharing this code:). It really helps a lot:D

    But I think there is a small type error in the function OnServerAddPlayer

    "player = Instantiate(characters[chosenCharacter], startPos.position,startPos.rotation)as GameObject;"

    should be

    "player = Instantiate(characters[selectedClass], startPos.position,startPos.rotation)as GameObject;"

    So the server will use the NetworkMessage information (which client send to server)to Instantiate GameObject
     
  13. IAMBATMAN

    IAMBATMAN

    Joined:
    Aug 14, 2015
    Posts:
    272
    Hmm, I think you're right... That's odd... I copy pasted that from my game that worked. But reading through that bit I don't understand...
     
  14. FWMilos

    FWMilos

    Joined:
    Nov 13, 2017
    Posts:
    1
    This is very useful man! But can you explain that ......chosenCharacter = hero; . What should I put? Number of element or? Thanks in advance.
     
  15. AungKhaingPhyo51

    AungKhaingPhyo51

    Joined:
    Aug 31, 2018
    Posts:
    1
    if you have video tutorial, please show me.. i am beginner
     
  16. mhogan256

    mhogan256

    Joined:
    May 15, 2018
    Posts:
    1
    Just tried this out. Works like a hot dam. Thanks guys !!
     
  17. ManishOtaval

    ManishOtaval

    Joined:
    Apr 15, 2018
    Posts:
    4
    Why did you put
    Code (CSharp):
    1. public GameObject characterSelect;
    on line 7 and
    Code (CSharp):
    1. characterSelect.SetActive(false);
    on line 12
     
  18. ManishOtaval

    ManishOtaval

    Joined:
    Apr 15, 2018
    Posts:
    4
    I tested it. Now both players (client / server) have the same character. You cannot change the player on behalf of the client.
     
  19. Licross

    Licross

    Joined:
    Nov 10, 2019
    Posts:
    1
    hello,
    This code is not working for me, since the client is going to start before you click the buttom, and it is not waiting for the function buttom script to be called, it will generate the client player with the default chosenCharacter value.

    It was very helpful, but I still can not get this to work. I would appreciate your help guys.

    Regards,
    Licross