Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
3
Question by Syndias · Jun 16, 2015 at 04:48 PM · networkingspawnrespawn

Spawning a new player instance (UNET)

I'm playing around with the new networking system, and I can't seem to figure out how to spawn a new player instance.

When a player reaches 0 health (or less), I execute the following code on the player GameObject:

 NetworkServer.Destroy(gameObject);

// UPDATE: I think I should be using ReplacePlayerForConnection, so added this in code below

After this, I show the respawn GUI (which is just a button right now). When you click the button, it should create a new instance of the player prefab. I tried implementing it like this:

 GameObject player = Instantiate<GameObject>(playerPrefab);
 NetworkServer.Spawn(player);
 NetworkServer.ReplacePlayerForConnection(NetworkManager.singleton.client.connection, player, NetworkManager.singleton.client.connection.playerControllers[0].playerControllerId);


But when I check the GameObject, its isLocalPlayer property isn't true.

I'm not sure about the parameters of ReplacePlayerForConnection. It looks like this should be possible a lot easier than this...

All the UNET examples don't destroy the GameObject, but just hide it. However, I want the player to be able to choose between different prefabs I created in the project (e.g. sniper, warrior, scout, whatever...), so that's not an option.

Other stuff I tried adding:

 NetworkClient.connection.playerControllers[0].gameObject = player; // get the local clients connection, get the first playerController (which is the only one) and assign the new player gameobject as its gameobject.

Which doesn't work.

Anyone having any luck with this?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

3 Replies

· Add your reply
  • Sort: 
avatar image
2

Answer by WillTM · Jun 17, 2015 at 03:15 PM

I think you need to invoke the replacement on the server using a [Command]

 [Command]
 void CmdReplaceMe(GameObject newPlayerObject)
 {
    NetworkServer.Spawn(newPlayerObject);
    NetworkServer.ReplacePlayerForConnection(connectionToClient, newPlayerObject, playerControllerId);
 
 }

Or something similar ( I still just experimenting myself tbh)

hope that helps :)

Comment
Add comment · Show 7 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Syndias · Jun 17, 2015 at 03:29 PM 0
Share

Thanks! I've tried to implement this:

     [Client]
     public void Respawn()
     {
         CmdRespawn();
     }
 
     [Command]
     public void CmdRespawn()
     {
     GameObject player = Instantiate<GameObject>(playerPrefab);
         Network$$anonymous$$anager.singleton.client.connection.playerControllers[0].gameObject = player;
         NetworkServer.ReplacePlayerForConnection(Network$$anonymous$$anager.singleton.client.connection, player, 0);
 }

But it's still not working

avatar image WillTM · Jun 17, 2015 at 03:43 PM 0
Share

ok so I think I'm slightly further than you but not by much :/. my 'replacement' player objects are already in the scene tho.. so try moving the instantiate to the client side before you call the command and pass the reference into the command. make sure the replacement prefab is in the netmanager spawnables and has a net identity too i guess?

avatar image Syndias · Jun 17, 2015 at 04:04 PM 0
Share

Something more like this?

     [Client]
     public void Respawn()
     {
         GameObject player = Instantiate<GameObject>(playerPrefab);
         NetworkServer.Spawn(player);
         NetworkInstanceId id = player.GetComponent<NetworkIdentity>().netId;
         CmdRespawn(id);
     }
 
     [Command]
     public void CmdRespawn(NetworkInstanceId id)
     {
         GameObject player = NetworkServer.FindLocalObject(id);
         NetworkServer.ReplacePlayerForConnection(Network$$anonymous$$anager.singleton.client.connection, player, 0);
         NetworkServer.DestroyPlayersForConnection(Network$$anonymous$$anager.singleton.client.connection);
     }

But I'm still getting the same error...

avatar image WillTM · Jun 17, 2015 at 07:03 PM 0
Share

I think you may be able to do this in your case

     public void Respawn() {
         
         CmdRespawn(playerPrefab); 
 //clean up old player separately
      }
          
      [Command]
      public void CmdRespawn(GameObject playerPrefab)
      {
     //as you are just instantiating the prefab reference according to docs you can do this
         NetworkServer.ReplacePlayerForConnection(connectionToClient, playerPrefab, 0);
 }

Im not using this Network$$anonymous$$anager.singleton.client.connection but connectionToClient, I get errors if I try it from a Command.. also may not want to destroy the player connection you have just replaced? my understanding is that would be if the client left the game though I may be wrong.

avatar image Syndias · Jun 18, 2015 at 08:34 AM 0
Share

The following code works when the client is the host:

 [Client]
     public void Respawn()
     {
         Debug.Log(currentPlayerGameObject.GetComponent<NetworkIdentity>().netId);
         CmdRespawn(currentPlayerGameObject.GetComponent<NetworkIdentity>().netId);
     }
    
     [Command]
     public void CmdRespawn(NetworkInstanceId playerNetId)
     {
         GameObject oldPlayer = NetworkServer.FindLocalObject(playerNetId);
         var conn = oldPlayer.GetComponent<NetworkIdentity>().connectionToClient;
         var newPlayer = Instantiate<GameObject>(playerPrefab);
        
         Destroy(oldPlayer.gameObject);
        
         NetworkServer.ReplacePlayerForConnection(conn, newPlayer, 0);
         Camera.main.GetComponent<FollowTarget>().target = newPlayer.transform;
     }

A second client however gets the warning: "Trying to send command for non-local player. UnityEngine.Networking.NetworkBehaviour:SendCommandInternal(NetworkWriter, Int32, String)" And nothing happens... Still not sure what's up with that...

Show more comments
avatar image
1

Answer by csisy · Jun 18, 2015 at 11:27 AM

What's about destroying and recreating the player? I mean when the health drops to 0 on the server, call

 NetworkServer.Destroy(player);

which will destroy the specified game object. If you know the NetworkConnection, you can query the corresponding player object if you didnt store it.

 NetworkPlayer player;
 if (conn.GetPlayer(playerControllerId, out player))
 {
     if (player.NetworkIdentity != null && player.NetworkIdentity.gameObject != null)
         NetworkServer.Destroy(player.NetworkIdentity.gameObject);
 }

If you have only one player object for each client, then you can call

 NetworkServer.DestroyPlayersForConnection(connection);

When you press the respawn button on the client, call the

 ClientScene.AddPlayer(0);

which will ask the server to spawn the specified player prefab.

At the bottom of this page, you can find some code which could help you.

Edit: I just read that you'd like to spawn other object. Well... AFAIK you can have more player for each connection so you could do the following:

  1. Spawn a "Connection" player which doesn't change

  2. The Connection object can be used to communicate with the server

  3. When the Client press the Respawn button, a message (Command) is sent to the server which would setup which object you want to spawn (sniper, warrior, etc.) using the Connection object.

  4. At the Server-side, you store the prefab for playerControllerId 1

  5. The client sends the add player request for id 1, by calling ClientScene.AddPlayer(1)

  6. In the Server, if you're using the NetworkManager, you can override the OnServerAddPlayer function

  7. Here you can check if the playerControllerId is 1, you spawn the stored prefab object.

Or something like this...

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by seanr · Jun 17, 2015 at 04:58 AM

try NetworkServer.ReplacePlayerForConnection()

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Syndias · Jun 17, 2015 at 09:16 AM 0
Share

Thanks! I was just experimenting with this, but have difficulties with filling in the correct parameters.

First parameter is the "Connection which is adding the player." So I use Network$$anonymous$$anager.client.connection

Second is the "Player object spawned for the player." So in my case, I use the instantiated gameObject from the code above (player)

Third parameter is "The player controller ID number as specified by client." I think this is where things go wrong. I tried using Network$$anonymous$$anager.client.connection.playerControllers[0].playerControllerId because there should be only one connection on the client. This seems to work (most of the time) when the client is also the server, but doesn't seem to work on a second client.

So the function call I use is:

 NetworkServer.ReplacePlayerForConnection(Network$$anonymous$$anager.client.connection, player, Network$$anonymous$$anager.client.connection.playerControllers[0].playerControllerId);

Any ideas what it is I'm doing wrong?

avatar image Syndias · Jun 17, 2015 at 09:34 AM 0
Share

I read on http://forum.unity3d.com/threads/switching-between-several-player-objects.333649/ that the new GameObject should already be spawned on the server before calling the ReplacePlayerForConnection function.

Right now I was doing the following:

 GameObject player = Instantiate<GameObject>(playerPrefab);
 NetworkServer.ReplacePlayerForConnection(Network$$anonymous$$anager.client.connection, player, Network$$anonymous$$anager.client.connection.playerControllers[0].playerControllerId);
 NetworkServer.Spawn(player);

However, am I right in thinking It should be the other way around?

 GameObject player = Instantiate<GameObject>(playerPrefab);
 NetworkServer.Spawn(player); // first spawn!!!
 NetworkServer.ReplacePlayerForConnection(Network$$anonymous$$anager.client.connection, player, Network$$anonymous$$anager.client.connection.playerControllers[0].playerControllerId);
avatar image seanr · Jun 17, 2015 at 12:48 PM 0
Share

if there is one player per client, then it should always be zero.

avatar image Syndias · Jun 17, 2015 at 01:00 PM 0
Share

Still not able to get this thing to work. This is my code:

         GameObject player = Instantiate<GameObject>(playerPrefab);
 
         NetworkServer.Spawn(player);
         NetworkServer.ReplacePlayerForConnection(Network$$anonymous$$anager.singleton.client.connection, player, Network$$anonymous$$anager.singleton.client.connection.playerControllers[0].playerControllerId);

But I keep getting the following error:

 Local invoke: Failed to find message handler for message ID 4
 UnityEngine.Networking.NetworkServer:ReplacePlayerForConnection(NetworkConnection, GameObject, Int16)
 Game$$anonymous$$anager:Respawn() (at Assets/SA$$anonymous$$BA/Scripts/Game$$anonymous$$anager.cs:20)
 UnityEngine.EventSystems.EventSystem:Update()
avatar image $$anonymous$$ Syndias · Aug 07, 2019 at 03:23 AM 0
Share

hi, @Syndias did you find the solution ?

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

8 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

MLAPI spawn player prefab 2 Answers

GameObject is spawned twice 0 Answers

Spaw dynamic (unregistered) object on network (UNET) 0 Answers

Unity Photon syncing objects 0 Answers

Can't set timer 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges