Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

UNET: Spawning different player prefabs (SOLVED)

Discussion in 'UNet' started by lejean, Feb 23, 2016.

  1. lejean

    lejean

    Joined:
    Jul 4, 2013
    Posts:
    392
    This is getting ridiculous, I've been searching nearly all day for something that shouldn't be this hard.

    I just want to have different player meshes join the same game, you know like most games...

    All prefabs work individually, but no matter what I do, the prefab that the host choses is the one that all the clients get when they join.

    Both prefabs have been added to the registered network prefabs in the networkmanager. I have a class selector screen so the player prefab in the networkmanager gets set according to those prefabs like so.

    Code (CSharp):
    1. if(ChosenClass==CharacterClasses.Ronin){
    2. NetworkManager.singleton.playerPrefab =NetworkManager.singleton.spawnPrefabs[0];
    3. }
    I've tried OnServerAddPlayer
    Code (CSharp):
    1. publicoverridevoidOnServerAddPlayer(NetworkConnection conn,short playerControllerId){
    2. var player =(GameObject)Instantiate(playerPrefab,ActManager.singleton.SpawnObject.transform.position,Quaternion.identity);
    3. NetworkServer.AddPlayerForConnection(conn, player, playerControllerId);
    4. }
    This simply doesn't work.

    Is this normally the way to do it, or is there more that should happen or something?

    Thx
     
    virtueone likes this.
  2. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Are your prefabs inside your "Resources" folder? if not it wont work..
     
  3. lejean

    lejean

    Joined:
    Jul 4, 2013
    Posts:
    392
    Well I have not tried that, but to be fair, it's not like that's documented somewhere.
    At least not from what could find.
    I'll get back to you.
     
  4. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    True :) hope that does it ;)
     
  5. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    This is completely incorrect based on the way he's writing his code.

    Now to address the original OP. You've been searching all day...but have you been searching your own work? What I mean by this, is look at WHAT you're trying to accomplish. Look at HOW you're trying to accomplish it. Then go through your code step by step to make sure every piece is working the way it's intended. First of all, why are you bothering to change the player prefab? Why not just put your IF statement inside of your override for the OnServerAddPlayer() method?
    Code (CSharp):
    1. public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId)
    2. {
    3.      if(/*PLAYER CHOOSES CLASS A*/)
    4.           //SPAWN THAT PREFAB
    5.    
    6.      if(/*PLAYER CHOOSES CLASS B*/)
    7.           //SPAWN THAT PREFAB
    8. }
    Next. I don't know if you messed it up just here, or in your own code too (although I would assume you would have seen an error thrown, but your syntax is screwed up...
    ...should be...
    Code (CSharp):
    1. public override void OnServerAddPlayer(NetworkConnection conn,short playerControllerId)
    Finally, you're not being clear on exactly WHAT results (if any) you're getting. Are you saying that you get no errors, but the GameObject also isn't spawned at all? Make sure to check you hierarchy to see if the prefab was spawned at all.
     
  6. lejean

    lejean

    Joined:
    Jul 4, 2013
    Posts:
    392
    I tried it that way too DRRosen3, calling the prefabs in OnServerAddPlayer, the syntax is also correctly typed, it's just the forum code that messed up.

    As to what happens, it's in bold on top.
    The host chooses model A and creates a game, all clients that connect also get model A regardless of what model they chose. The models do get changed when I look at the networkmanager's playerprefab variable in the inspector. They just won't instantiate the correct one when the scene loads. Everything works, even the gear that they have in their inventory.

    It's almost as if the playerprefab variable is shared amongst the network and can't be changed.
    Putting it in resources didn't work either.
     
    ItsAtomTime and hardik18csu076 like this.
  7. lejean

    lejean

    Joined:
    Jul 4, 2013
    Posts:
    392
    Also //SPAWN THAT PREFAB is kind of the code I need.
    I've just been following this manual http://docs.unity3d.com/Manual/UNetPlayers.html
     
  8. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    You said you tried it... "Putting it in resources..." What exactly did you do and did you change you code at all after putting it in resources? I have multiple player objects as well and that's exactly how I spawn mine...via Resource Loading.
     
  9. lejean

    lejean

    Joined:
    Jul 4, 2013
    Posts:
    392
    I still use the spawnprefabs[0], cause those are the prefabs in the networkmanager.
    I just dragged the reference to resources, cause maybe they just need to be in the resources folder for what ever reason.

    But I have not tried resources.load specifically, which I'll do now.
     
  10. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    First, make sure your prefabs are in a folder named Resources. They can be in a subfolder, as long as the main folder is named Resources and is in the Assets folder.

    Code (CSharp):
    1. public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId)
    2. {
    3.      GameObject player;
    4.  
    5.      if(chosenClass == CharacterClasses.Ronin)
    6.           player = Instantiate(Resources.Load("Ronin Prefab"), transform.position, Quaternion.identity) as GameObject;
    7.  
    8.      if(chosenClass == CharacterClasses.Samurai)
    9.           player = Instantiate(Resources.Load("Samurai Prefab"), transform.position, Quaternion.identity) as GameObject;
    10.  
    11.      NetworkServer.AddPlayerForConnection(conn, player, playerControllerId);
    12. }
     
  11. lejean

    lejean

    Joined:
    Jul 4, 2013
    Posts:
    392
    Nop simply doesn't work, I just made an new scene with 2 different dummies to prevent other scrips from messing with it.
    The host still choses the model.

    Code (CSharp):
    1. public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId) {
    2.         //base.OnServerAddPlayer(conn, playerControllerId);
    3.         if (chosenCharacter) {
    4.             GameObject player = Instantiate(Resources.Load("Characters/A", typeof(GameObject))) as GameObject;
    5.             NetworkServer.AddPlayerForConnection(conn, player, playerControllerId);
    6.         }
    7.         else {
    8.             GameObject player = Instantiate(Resources.Load("Characters/B", typeof(GameObject))) as GameObject;
    9.             NetworkServer.AddPlayerForConnection(conn, player, playerControllerId);
    10.         }
    11.     }
    I have a feeling that the clientscene needs to do something too.

    That code does work for you without any other scripting tho?
     
  12. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Yes my code works. Keep in mind OnServerAddPlayer() is called on the server. If you're choosing your "chosenCharacter" on the client, the server needs some way to know which character the client has chosen.
     
  13. lejean

    lejean

    Joined:
    Jul 4, 2013
    Posts:
    392
    Well that's most likely the problem, cause I am doing it client side and I didn't know OnServerAddPlayer was server side.
    So how would I go about this?
    Is it possible to have an offline scene send which character you selected, or does the class selection need to be online as well?
     
  14. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Offline or online doesn't matter. The problem is changing the playerPrefab on the client won't change it on the server. The NetworkManager is the same for both the server and the client when you build the game. So let's say Ninja is in the playerPrefab slot when you build it. If you log onto the game as a client, and change the playerPrefab to Samurai by pressing a button, it only changes the playerPrefab for the client. The server still thinks the playerPrefab is the Ninja. That's why you have to use something like Resources.Load. However, the only way to make this work is to let the server know which prefab the player wants to load from the Resources folder. You're going to have to look into the second OnServerAddPlayer() method which takes 3 arguments. This is where my help is going to fall short, as I haven't played around with this much yet. However, these two code snippets are taken from the base NetworkManager.cs.
    Code (CSharp):
    1. internal void OnServerAddPlayerMessageInternal(NetworkMessage netMsg)
    2. {
    3.      if (LogFilter.logDebug) { Debug.Log("NetworkManager:OnServerAddPlayerMessageInternal"); }
    4.  
    5.             netMsg.ReadMessage(s_AddPlayerMessage);
    6.  
    7.             if (s_AddPlayerMessage.msgSize != 0)
    8.             {
    9.                 var reader = new NetworkReader(s_AddPlayerMessage.msgData);
    10.                 OnServerAddPlayer(netMsg.conn, s_AddPlayerMessage.playerControllerId, reader);
    11.             }
    12.             else
    13.             {
    14.                 OnServerAddPlayer(netMsg.conn, s_AddPlayerMessage.playerControllerId);
    15.             }
    16.         }
    Code (CSharp):
    1.         public virtual void OnServerAddPlayer(NetworkConnection conn, short playerControllerId, NetworkReader extraMessageReader)
    2.         {
    3.             OnServerAddPlayerInternal(conn, playerControllerId);
    4.         }
    The entire script can be viewed HERE.
     
    KrakenKoders likes this.
  15. lejean

    lejean

    Joined:
    Jul 4, 2013
    Posts:
    392
    Ye I was already looking in to the networkmessage, but surprise surprise the documentation is severely lacking :p

    On a side not tho, wouldn't that mean my prefab should still be correct on the client side, and wrong on the server side, cause right now it's wrong on both sides.

    Anyway, thanks alot for your help mate, you helped me in the right direction :)
     
    harryvzhvr and Fireshore like this.
  16. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Really? how are you able to instantiate prefabs outside the Resource folder? I want to know this ..
    And why is using Resource folder totally wrong? o_O
     
  17. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    To instantiate prefabs outside of Resource folders, just get a game object with the target prefab set in that game object's Inspector properties, then in the script component attached to the target prefab, call on MonoBehaviour.Instantiate(yourPrefab);

    I'm not sure about the Resource folder. All I know is Resource folder is the same as Assets folder, except the Resource folder have a helper class that supports doing stuffs with the resources.
     
  18. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    To be a but more clear on what @asperatology is saying. You can Instantiate a prefab by declaring it as a variable in a script. By making the variable public...once you attach the script to a GameObject, you can then drag your prefab into the variable's slot in the inspector.

    As for why using Resource was wrong... It wasn't wrong in of itself. You told him it wouldn't work unless he put the prefab in a Resource folder. THAT was wrong. The only time a prefab needs to be in a Resource folder, is if you're using Resources.Load. Otherwise, you'll have to use the method that @asperatology and I described above.
     
  19. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Code (CSharp):
    1.  GameObject player = Instantiate(Resources.Load("Characters/B",
    Ehh wrong , that will not work unless you use normal instantiate .. Resources.Load is target path to the Resource folder else it will return null. Using Resources.Load is a better practice if you experiencing issue with prefabs, because you have better control. Hence my tip in the first place..

    Read the documents ..
     
  20. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    Oh, OP is referring to loading a prefab from Resources folder? I guess I misread the entire thread.
     
  21. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    lol You should probably try and not only read the documents yourself, but put some of them into practice. Using Resources.Load is not better practice than using a variable. You have better control using a public variable of type GameObject because you simply drag and drop the EXACT prefab you want to use into the inspector, no matter what folder it exists in inside the Assets folder. Using Resources.Load you have to worry about getting the syntax (the string path) EXACTLY right. One wrong character and it'll throw an error.
     
  22. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Who said anything about typing a string manually? Only your own example does, that is not a recommend way of doing this, and you totally forgot to tell him to use SerializeField there is a pretty big reason you need that..

    I show here a complete way of doing this. And the reason for my recommendation is because OP had issue with prefab
    when working with networking instantiate, it fixed problems before when using networking and prefabs.

    Code (CSharp):
    1.  
    2.  
    3. [SerializeField]
    4. public GameObject ThePlayerPrefab; // from Resource folder only
    5. GameObject NewInstanceOfPlayer;
    6. public Vector3 playerSpawnPos;
    7. public string PlayerName;
    8.  
    9.   private void SpawnPlayer(NetworkConnection con) // for this connection
    10.    {
    11.      NewInstanceOfPlayer = Instantiate(Resources.Load(ThePlayerPrefab.name,
    12. playerSpawnPos, Quaternion.identity )) as GameObject;
    13. NewInstanceOfPlayer.name = PlayerName;
    14.      NetworkServer.AddPlayerForConnection(con, NewInstanceOfPlayer, 0);
    15.    }
    16.  
    17.  
    18.  
    Also make sure your Prefab has a camera attached to it, and that auto spawning of players
    is turned off in the Networkmanager

    I hope this helps you Lejean , else the issue is not with prefabs.
     
    Last edited: Feb 24, 2016
  23. lejean

    lejean

    Joined:
    Jul 4, 2013
    Posts:
    392
    Ye, I got it semi working yesterday and it doesn't have anything to do with the resources folder (well maybe, but that wasn't the original problem).

    It was exactly like ddrosen said that OnServerAddPlayer is a server side function, so you can't use a button to set a int, and then do OnServerAddPlayer and call a model according to that int.

    Once I had the server side spawn a different model hard coded, it did work. So now I'm trying to figure out how to use clientscene.addplayer with a custom message to tell the server what to load.

    I'm gonna try out your way later Ironmax, cause know I'm getting errors because I'm doing a manual clientscene.addplayer, and he sais "Connection already set up, blabla".

    Thx for the help anyway :)
     
  24. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Happy its working better for you, that error msg, did you try turning off auto spawning in the networkmanger settings?

    Its very important to distinct what is going on server sided and was is playerlocal. And it looks like that was your issue here and not prefab setup.

    My general tip here is that "don't trust the inspector" :)
     
    Last edited: Feb 24, 2016
  25. lejean

    lejean

    Joined:
    Jul 4, 2013
    Posts:
    392
    Ok I got it working, so I'll post a code example for future people searching for the same problem.
    So this allows for a character selection from the offline scene. It sends a networkmessage with clientscene.addplayer with the chosen selection.
    Only the OnClientSceneChanged needs to be overridden and the base commented out, otherwise I still get the "Connection already set up,.."

    Code (CSharp):
    1. public class NetworkCustom : NetworkManager {
    2.  
    3.     public int chosenCharacter = 0;
    4.  
    5.      //subclass for sending network messages
    6.      public class NetworkMessage : MessageBase {
    7.         public int chosenClass;
    8.     }
    9.  
    10.     public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId, NetworkReader extraMessageReader) {
    11.         NetworkMessage message = extraMessageReader.ReadMessage< NetworkMessage>();
    12.         int selectedClass = message.chosenClass;
    13.         Debug.Log("server add with message "+ selectedClass);
    14.  
    15.         if (selectedClass == 0) {
    16.             GameObject player = Instantiate(Resources.Load("Characters/A", typeof(GameObject))) as GameObject;
    17.             NetworkServer.AddPlayerForConnection(conn, player, playerControllerId);
    18.         }
    19.  
    20.         if (selectedClass == 1) {
    21.             GameObject player = Instantiate(Resources.Load("Characters/B", typeof(GameObject))) as GameObject;
    22.             NetworkServer.AddPlayerForConnection(conn, player, playerControllerId);
    23.         }
    24.     }
    25.  
    26.     public override void OnClientConnect(NetworkConnection conn) {
    27.         NetworkMessage test = new NetworkMessage();
    28.         test.chosenClass = chosenCharacter;
    29.  
    30.         ClientScene.AddPlayer(conn, 0, test);
    31.     }
    32.  
    33.  
    34. public override void OnClientSceneChanged(NetworkConnection conn) {
    35.         //base.OnClientSceneChanged(conn);
    36.     }
    37.  
    38. public void btn1() {
    39.         chosenCharacter = 0;
    40.     }
    41.  
    42.     public void btn2() {
    43.         chosenCharacter = 1;
    44.     }
    45. }
     
  26. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    Thanks for posting a follow-up solution.
     
  27. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Dear lord...you have absolutely NO idea what you're doing. This is EXACTLY what @asperatology and I said to do. No you DO NOT HAVE TO USE Resources.Load.. Stop giving people bad information. What if the prefab isn't in the Resources folder? What if it's inside of a folder, inside of a folder, inside the Resources folder? You DO have to type the string path name out. Not to mention you're writing unnecessary code.

    In any case...glad to be of help and even more glad you got it working.
     
    KyleOlsen likes this.
  28. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Have you ever wondered why no one is backing you up...ever? Maybe it's time to get your head out of your rear and look into why everyone (in multiple threads...I've looked you up) says you're wrong constantly.
     
  29. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Step 1 - Click on your own name.
    Step 2 - Go to your profile page.
    Step 3 - Scroll down to the "Interact" category on your page.
    Step 4 - Under the "Content" sub-category, click on "Find all content by Ironmax".
    Step 5 - Review the threads where you said/suggested things.
    Step 6 - You'll discover that nobody has EVER supported or backed you up in any capacity.

    Now, if you're too stupid (because you can't claim ignorance when I've laid it out for you step by step) to do that, and see what I mean, then that's your own problem. No I don't know you, and I don't want to know someone so ignorant...or stupid (seeing as I don't know your educational background). However, you're the idiot that decided to get online with whatever farfetched knowledge you scraped together, and started trying to give people advice without thinking that maybe someone would do a bit of research on you (your history in this forum) and see that nothing you say has ever been accepted by anyone in this community. That said...again I hope you pull your head out of your rear- ...wait...you've already proven you're not going to do that. Anywho, I'm done with this thread since the OP has solved his issue.
     
    KyleOlsen likes this.
  30. mubi

    mubi

    Joined:
    Feb 20, 2016
    Posts:
    1
    hi lejean, i am also going through the same problem which you have suffered, spawning different prefabs in server and in client. i have seen your code it is working fine but the problem is that in server i am able to see server object and also client's object when it joins but in client scene, there is no server object only client alone..
     
  31. Lexeon

    Lexeon

    Joined:
    Apr 22, 2016
    Posts:
    23
    Pertaining to an argument above, I'm just putting this here for future reference for anyone that stumbles upon this thread in the future. Drag and drop is the way to go almost all the time, since is it much more easier to create a variable and drop your prefab into it VS having to look up the file path and hardcoding the path into it. It is also much more easier to organize and keep track of what does what. And since humans are intuitively lazy (programmers especially), drag and drop is a better and faster way to get a prefab up and running. If you're on a schedule and you have to ship someday, you're going to need all the time you got, and it's not time well spent messing with something if there is an easier and more effective way. Trust the inspector, the only reason it has to lie to you is based on your own organizational skills.

    Anyway, thanks for posting your code, lejean. I got mine working too.
     
    TomCorwine, KyleOlsen and Salim like this.
  32. Keeganz

    Keeganz

    Joined:
    Jun 10, 2016
    Posts:
    2
    Lexeon can you post how you did it?!
     
  33. Keeganz

    Keeganz

    Joined:
    Jun 10, 2016
    Posts:
    2
    Lejean, where do i put this script?!
     
  34. Wojalin

    Wojalin

    Joined:
    Jun 29, 2016
    Posts:
    2
  35. KillitsGaming

    KillitsGaming

    Joined:
    Aug 24, 2014
    Posts:
    28
    Hi it works for me but when the client joins the host, the client wont spawn
    and dont know what for OnClientSceneChanged
     
  36. Daggett110

    Daggett110

    Joined:
    Jul 21, 2015
    Posts:
    1
    First of all, the work that you guys have done here has saved me a ton of hassle. I did however notice that when I tried to use this in a lobby Manager setting, that it doesn't quite work the same since OnServerAddPlayer actually calls when a player joins the lobby rather than when the lobby players join the game. Has anyone had success with implementing this into a lobby system yet? I tried connecting it to Unity's free Lobby package that they released on the Asset store to little success.
     
  37. IAMBATMAN

    IAMBATMAN

    Joined:
    Aug 14, 2015
    Posts:
    272
    Thank you guys :p
     
  38. jeango

    jeango

    Joined:
    Dec 19, 2012
    Posts:
    109
    You people are my heroes :D
     
  39. ZurdoRod

    ZurdoRod

    Joined:
    Mar 7, 2015
    Posts:
    2
    It didnt work for me. Everytime a client connects, all the old players change their prefabs to the new one -.-!
     
  40. eating2016

    eating2016

    Joined:
    Aug 1, 2016
    Posts:
    5

    Just the right answer to my problem, thanks a lot!!! :):):):D:D:D
     
  41. MrDude

    MrDude

    Joined:
    Sep 21, 2006
    Posts:
    2,569
    First off, thanks very much for this. I only started looking at networking this week and this was the one thing I could not figure out how to do. I noticed in the docs it said "If you have a prefab you want to load for all clients, drag it into Network manager and if you want to load different prefabs, do so inside that function you override" (paraphrasing) but they never said WHAT to put inside the overload. So yeah, you saved me a bunch searching and struggling. Looking forward to testing this code out soon :D Thanks again.

    And just to throw my 2 cents into the ring... I was reading about those two taking each other on and was just sitting here smiling as they both claim the other to be the idiot and yet they are both wrong. lol :p I've been using the Resources.Load function for more than 7 years and have sold assets that make EXTENSIVE use of it, earning me 5 figure incomes and loads of praise for those assets, so I think I am worth hearing out...

    First of all, if you HAVE a prefab placed in a public variable then there is NO NEED to use Resource.Load... This is fine:
    Code (csharp):
    1. public GameObject the_prefab;
    2. GameObject spawned = Instantiate(the_prefab);
    Secondly, ALL RESOURCES FOLDERS HAVE THEIR CONTENT PILED INTO ONE RESOURCES FOLDER when the project gets built. It doesn't matter WHERE your resources folder is located, you do NOT need to specify the path to it, and in fact, if you DO it will break post build because the path will no longer exist. I.e. Assets/mykit/subfolder/Resources/myprefab will still load 100% fine using
    Code (csharp):
    1. Resources.Load("myprefab");
    The problem here is that you can have 50 Resources folders scattered all around the project and each of them can have prefabs with the same name. If you use Resources.Load like I did above then you have no idea what resource you will end up loading if you have multiple with the same name. Thus, if you HAVE a public variable, then USE it! Instantiate that directly.

    Saying
    Code (csharp):
    1. Resources.Load(myprefab.name);
    brings you to the same problem as before... Your asset's name is "foobar" and you have 50 Resources folders of which 3 contain a prefab called "foobar". The code above means you have no idea which one will load...

    Now, on another note, if you place a folder (or nested folders) inside the Resources folder, THAT will get copied over as is so if you have a folder like this: Assets/mygame/mycontent/Resources/characters/samurai and another one Assets/Textures/Resources/avatars/samurai, the following will both fail:
    Code (csharp):
    1. Resources.Load("samurai");
    2.  
    3. public GameObject myprefab;
    4. Resources.Load(myprefab.name);
    Since the folders are INSIDE the Resources folders you now have to specify them when you load the resource... but notice how the path BEFORE the resources is of no consequence...
    Code (csharp):
    1. GameObject player = Resources.Load("characters/samurai") as GameObject;
    2. Texture mytex = Resource.Load("avatars/samurai", typeof(Texture2D)) as Texture2D;
    3.  
    4. //on a side note, I like to combine my resource loading and instantiation into one...
    5. Movement player = Instantiate<Movement>(Resources.Load<Movement>("characters/"+charactername));
    6. player.avatar = Resources.Load<Texture2D>("avatars/"+charactername);
    7. //this saves me from having to do a: Movement m = player.GetComponent<Movement>();
    8. //but that is just me... and totally of topic. Fin.
    9.  
    Right, now that we are all sorted on the use of prefabs there is only one thing left on my mind, personally, that I have yet to go test. Like I said, I am intimately familiar with using Resources.Load but I am incredibly inexperienced with Unity networking... I could have sworn that I read somewhere that when using networking your assets have to be in a Resources folder. I know this was true for ULink but not sure if this is true for UNET also... so very unclear about that.

    Fetching the prefabs from the list in the NetworkManager is a great way to access them by reference and under normal circumstances I would just instantiate it directly from that (direct reference in the array)... but I seem to recall something about when you are doing network instantiation, then the prefabs STILL need to be in Resources folders even though you just say Instantiate(prefab[1]) and don't use Resource.Load at all... Is this true or not? That is my only mystery now... Simple enough to test, I guess... :)
     
    Last edited: Mar 10, 2017
  42. angusmf

    angusmf

    Joined:
    Jan 19, 2015
    Posts:
    261
    Nope. Serialized prefabs in the scene objects are fine. I use a mix of both.
     
    KyleOlsen and MrDude like this.
  43. MrDude

    MrDude

    Joined:
    Sep 21, 2006
    Posts:
    2,569
    Thanks for the heads up :)
     
  44. ajaybhojani

    ajaybhojani

    Joined:
    Dec 3, 2013
    Posts:
    7
    Hi all.. Finally there is solution of all above stuff with video.
    Please refer video to generate selected player prefab using UNET.


    Thanks to Jill Hoffman...!!!
     
    BahuMan and BryanO like this.
  45. Paradoks

    Paradoks

    Joined:
    Oct 13, 2009
    Posts:
    436
    Hello,

    I am trying to appy the @lejean way, and can't make it work in any ways.
    Could someone point me out what i am doing wrong ?

    first i got a class for the message
    Code (CSharp):
    1. public class CharacterSelectionNetworkMessage : MessageBase {
    2.  
    3.     public int chosenClass;
    4. }
    then in my client side i do this:
    Code (CSharp):
    1. void SpawnCharacter(){
    2.  
    3.         CharacterSelectionNetworkMessage characterSelectedNumber = new CharacterSelectionNetworkMessage();
    4.         characterSelectedNumber.chosenClass = selectedCharacter;
    5.         ClientScene.AddPlayer(ClientScene.readyConnection, 0, characterSelectedNumber);
    6.  
    7. }
    On the server side i do this:
    Code (CSharp):
    1.     public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId, NetworkReader extraMessageReader){
    2.     //public override void OnServerAddPlayer(UnityEngine.Networking.NetworkConnection conn, short playerControllerId, NetworkReader extraMessageReader){
    3.         base.OnServerAddPlayer (conn, playerControllerId, extraMessageReader);
    4.  
    5.         CharacterSelectionNetworkMessage message = extraMessageReader.ReadMessage< CharacterSelectionNetworkMessage>();
    6.         int selectedClass = message.chosenClass;
    7.         Debug.Log("server add with message "+ selectedClass);
    8.  
    9.         //playerPrefab = entityToSpawn [selectedClass];
    10.  
    11.         GameObject player = Instantiate(entityToSpawn [selectedClass]) as GameObject;
    12.  
    13.         NetworkServer.AddPlayerForConnection (conn, player, playerControllerId);
    14.         //NetworkServer.AddPlayerForConnection (conn, entityToSpawn [selectedClass], playerControllerId);
    15.  
    16.         MasterSceneManager.staticMasterSceneManager.SetTime();
    17.         MasterSceneManager.staticMasterSceneManager.UpdateItemsForNewPlayer ();
    18.     }
    And nothing happens ... i think i tried every combinations with no success, any idea what i am doing wrong ?

    [EDIT]

    In fact, it spawn the GameObject that is in the prefab var, and when it is spawned i got this error message:
    ------------
    Assertion failed on expression: '!CompareApproximately(aScalar, 0.0F)'
    UnityEngine.Quaternion:Lerp(Quaternion, Quaternion, Single)
    ---------------
    Wich is coming from my movement sync script

    also forgot to say: if i spawn with the simple syntax ( ClientScene.AddPlayer (0);) the default prefab, i got no error.

    [EDIT]

    thanks.
     
  46. Paradoks

    Paradoks

    Joined:
    Oct 13, 2009
    Posts:
    436
    Forget about the error in the edit, in fact it spawn two time the player's prefab, the first one is the default one, the second is the one selected but the player dont have control over it.

    So the new question is: why is unet spawning a prefab two time ?
     
  47. n00bmind

    n00bmind

    Joined:
    Sep 5, 2017
    Posts:
    3
    Hi,
    I also cannot make @lejean solution work, but for different reasons..

    First off, @Paradoks, in your case if you don't want to instantiate two player prefabs you should simply never call base.OnServerAddPlayer(), since the default implementation of that method in the NetworkManager class already calls AddPlayer() for you.

    In my case, I'm also following this method, and the data is clearly getting to the server fine, in fact in the server all players are instantiated according to their selected configuration. The problem is, the clients never get to see this configuration anywhere. The object they spawn when they get the ObjectSpawn message is the default prefab, not the server configured instance.

    At this point, I guess I could make the localPlayer in each client send a Command to inform all other clients of their desired config, but then there's no point in subclassing a NetworkMessage etc.

    Any other ideas?
     
  48. lejean

    lejean

    Joined:
    Jul 4, 2013
    Posts:
    392
    Well seeing as I keep getting notifications from this thread I did another test with the project updated to 5.6.4.
    I just hosted in unity and joined through LAN in a build and it still works, so there's definitely something else wrong in your code.

    It's been a while since I've worked on this, so I'm not entirely sure what's wrong, but I'll post a screenshot of my network script cause I think the settings are your problem.

    So player prefab is empty, auto create player is checked and your different classes need to be assigned in the registered spawnable prefabs. These prefabs are located in the resources folder, and these are also the ones I instantiate in OnServerAddPlayer() as seen in the image. (Maybe this isn't necessary, but it works like this).

    The rest of the code you see above is exactly the same.
    This is also tested in a scene with only the network custom and the networkmanager HUD.
     

    Attached Files:

  49. n00bmind

    n00bmind

    Joined:
    Sep 5, 2017
    Posts:
    3
    Hi @lejean,
    Yes the problem is totally on my side. The thing is my approach to player configuration was different from the start. My intention was to setup my player prefab using a ScriptableObject when getting this message from the client, which doesn't work because all clients will instantiate the raw prefab when they get back the spawn message from the server no matter what I do server side.

    Using a different prefab for each different character, as you were doing, works perfectly however, so, even if it's not the way I'd prefer to do it, I'll go with this for the time being.

    Thanks a lot for the help.
     
  50. wilbeau97

    wilbeau97

    Joined:
    Feb 20, 2018
    Posts:
    1
    Hi @lejean I have a huge problem with my network custom, is it possible to show the entire script from the first line to the last, i'd like to see what else you do in these script