EDIT: I found the problem, it was my fault. Turns out that while I assumed identical objects dynamically created on the client and the server would identify the same, they don’t. They end up with different assetIds, and when the Server tells the Client to spawn it, the Client doesn’t understand the assetId, and thus panics and spawns the default player. As for how to actually do what I was originally meaning to do… Well, I haven’t found a way yet…
So I don’t know if this is intentional or not, but if you return a prefab in OnLobbyServerCreateGamePlayer, only the server is that prefab, the client remains the prefab you set as the Game Player Prefab.
The weirdest thing is that everything that can will still sync between the client and server (Meaning mainly the transform), even though they are two different prefabs…
Anyway, here’s my code so you can tell me if I’m doing something wrong:
function OnLobbyServerCreateGamePlayer(conn : NetworkConnection, playerControllerId : short){
if(gamePlayerPrefab == null){
if (LogFilter.logError) { Debug.LogError("The gamePlayerPrefab is empty on the NetworkManager. Please setup a gamePlayerPrefab object."); }
return;
}
if(gamePlayerPrefab.GetComponent.<NetworkIdentity>() == null){
if (LogFilter.logError) { Debug.LogError("The gamePlayerPrefab does not have a NetworkIdentity. Please add a NetworkIdentity to the player prefab."); }
return;
}
var poweredPlayerPrefab : GameObject = GetPoweredPlayerPrefabRandom();
if(!poweredPlayerPrefab){
if (LogFilter.logError) { Debug.LogError("No powered player prefab recieved."); }
return;
}
var spawnPoint : Transform = this.GetStartPosition();
var player : GameObject;
if(spawnPoint != null){
player = GameObject.Instantiate(poweredPlayerPrefab, spawnPoint.position, spawnPoint.rotation).gameObject;
player.SetActive(true);
}else{
if(LogFilter.logError){ Debug.LogError("Trying to spawn a gamePlayerPrefab with no spawn points."); }
return;
}
print("Player finished");
return player;
}
GetPoweredPlayerPrefabRandom() returns a link to a GameObject obtained from a list of GameObjects. The list is identical on both client and server, since it’s hard coded in, and every object in it is registered on both client and server using ClientScene.RegisterPrefab(). There’s nothing invalid about doing that which I know of.
If I screwed up, help is appreciated. If not, confirmation that this is a bug or tips on how to circumvent it would help too.
hey man, i met with the same problem, so did you have a solution by now?
No, unfortunately I didn’t. What I settled on doing was the player being a single, non-dynamically created prefab with all of the components it could possibly need on it from the start (you can’t add and remove components over networks). I then have a master controller script on the player which is networked which decides what the player looks like while setting up and syncing that.
Something that took me a while to figure out and might save you some time is that when the player has a networked script on it which you don’t want active (usually because you don’t need it for some of the players configurations), don’t disable the script. Setting the scripts enabled property to false screwed up all sorts of things if I remember right, and disable doesn’t even work for things like collisions. Instead, in every piece of the script, make it so that there’s an if statement which either checks a separate “isEnabled” property you made, or checks the master controller script to see if it’s the right configuration. Which of those two options is best will depend on how you need to customize the player.
Anyway, hope this helps a bit. It really does suck that we can’t do this. (One thing that might work but would be complex and beyond my capabilities is to send raw network messages with the GameObject generated to the clients after creating it with the server, then spawning it afterwards (you may have to yield to get this to work, assuming it even can work. Network Message documentation is here: http://docs.unity3d.com/Manual/UNetMessages.html. Another thing you could look at is that the high level networking code was released by Unity recently. This should allow you to customize the OnLobbyServerCreatePlayer() function so that it works like the OnServerAddPlayer() function, which does work like you’d expect in these matters).
Thanks for your reply,i’m not sure this is a bug, so i sent Unity Team a test demo to show what we met yesterday .I was intended to do thing like you said, i think this way is not intuitive but too complex. if i have 5 different heroes, it would be a very very “giant monster” for the player prefab… I also checked the source of the network system, i just found the “OnLobbyServerCreateGamePlayer” function which fits our intention, but it failed. The message system is too complex for me to handle, so i haven’t another way but to try things like you said.
hello again, i think i have figured out where we did wrong. In your script, “var poweredPlayerPrefab :GameObject= GetPoweredPlayerPrefabRandom();”
this is where the error happens. the prefab you create is not in the register slot, so the prefab will not be registered on the remote client, so the client can’t recognize the prefab. I move the prefabs to the register slot on the networkmanager, everything goes very well, so you can have a try!
Hey guys!
I know the last answers are old, but maybe some are still stuck with the problem.
Try this guys post:
Give him a cookie!