0
\$\begingroup\$

I am using two different objects for player in network multiplayer game. Two different kinds of gameobject will be instantiated by unity network behavior but the problem is there is only single property of playerprefab. How can i set two different objects even i tried to change it on run time but its giving me error.

Failed to spawn server object, assetId=4d293c8e162f3874b982baadd71153d2 netId=1 UnityEngine.Networking.NetworkIdentity:UNetStaticUpdate()

Failed to spawn server object, assetId=4d293c8e162f3874b982baadd71153d2 netId=7 UnityEngine.Networking.NetworkIdentity:UNetStaticUpdate()

\$\endgroup\$
1
\$\begingroup\$

In multiplayer Game object if you want to instantiate different gameobject for different player you have to inherit NetworkManager into your script and required its customization.

  1. Add this script to a gameobject

    public class NetworkManagerCustom2 : NetworkManager
    {
        public class MsgTypes
        {
            public const short PlayerPrefab = MsgType.Highest + 1;
    
            public class PlayerPrefabMsg : MessageBase
            {
                public short controllerID;
                public short prefabIndex;
            }
        }
    
        // in the Network Manager component, you must put your player prefabs 
        // in the Spawn Info -> Registered Spawnable Prefabs section 
        public short playerPrefabIndex;
    
    
        public override void OnStartServer()
        {
            Debug.Log("OnStartServer");
            NetworkServer.RegisterHandler(MsgTypes.PlayerPrefab, OnResponsePrefab);
            base.OnStartServer();
        }
    
        public override void OnClientConnect(NetworkConnection conn)
        {
            Debug.Log("OnClientConnect");
            client.RegisterHandler(MsgTypes.PlayerPrefab, OnRequestPrefab);
            base.OnClientConnect(conn);
        }
    
        private void OnRequestPrefab(NetworkMessage netMsg)
        {
            Debug.Log("OnRequestPrefab");
            MsgTypes.PlayerPrefabMsg msg = new MsgTypes.PlayerPrefabMsg();
            msg.controllerID = netMsg.ReadMessage<MsgTypes.PlayerPrefabMsg>().controllerID;
            msg.prefabIndex = playerPrefabIndex;
            client.Send(MsgTypes.PlayerPrefab, msg);
        }
    
        private void OnResponsePrefab(NetworkMessage netMsg)
        {
            Debug.Log("OnResponsePrefab");
            MsgTypes.PlayerPrefabMsg msg = netMsg.ReadMessage<MsgTypes.PlayerPrefabMsg>();
            playerPrefab = spawnPrefabs[msg.prefabIndex];
            base.OnServerAddPlayer(netMsg.conn, msg.controllerID);
            Debug.Log(playerPrefab.name + " spawned!");
        }
    
        public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId)
        {
            Debug.Log("OnServerAddPlayer");
            MsgTypes.PlayerPrefabMsg msg = new MsgTypes.PlayerPrefabMsg();
            msg.controllerID = playerControllerId;
            NetworkServer.SendToClient(conn.connectionId, MsgTypes.PlayerPrefab, msg);
        }
    
        // I have put a toggle UI on gameObjects called PC1 and PC2 to select two different character types.
        // on toggle, this function is called, which updates the playerPrefabIndex
        // The index will be the number from the registered spawnable prefabs that 
        // you want for your player
        public void UpdatePC()
        {
            Debug.Log("UpdatePC");
            if (GetComponent<NetworkManagerHUDCustom2>().isVR)
            {
                Debug.Log("UpdatePC" + 0);
                playerPrefabIndex = 0;
            }
            else //if (GameObject.Find("PC2").GetComponent<Toggle>().isOn)
            {
                Debug.Log("UpdatePC"+ 1);
                playerPrefabIndex = 1;
            }
    
        }
    }
    
    1. Add your Different Player objects prefabs in in above script's Registered Spawnable prefab list.

    2. Customize the NetworkManagerHUD so that after joining the server or creating the host you can provide player prefab index which has to instantiate. Complete script given below. I have added GUI toggle option so that if it is check a VR player will be instantiated otherwise a normal player will be instantiate.

.

using System;
using System.ComponentModel;
#if ENABLE_UNET

namespace UnityEngine.Networking
{
    [AddComponentMenu("Network/NetworkManagerHUD")]
    [RequireComponent(typeof(NetworkManager))]
    [EditorBrowsable(EditorBrowsableState.Never)]
    public class NetworkManagerHUDCustom2 : MonoBehaviour
    {
        public NetworkManager manager;
        [SerializeField]
        public bool showGUI = true;
        [SerializeField]
        public int offsetX;
        [SerializeField]
        public int offsetY;

        public GameObject vrPlayer;
        public GameObject normalPlayer;
        public bool isVR;
        // Runtime variable
        bool m_ShowServer;

        void Awake()
        {
            manager = GetComponent<NetworkManager>();
        }

        void Update()
        {

            if (!showGUI)
                return;

            if (!manager.IsClientConnected() && !NetworkServer.active && manager.matchMaker == null)
            {
                if (UnityEngine.Application.platform != RuntimePlatform.WebGLPlayer)
                {
                    if (Input.GetKeyDown(KeyCode.S))
                    {
                        manager.StartServer();
                    }
                    if (Input.GetKeyDown(KeyCode.H))
                    {
                        manager.StartHost();
                    }
                }
                if (Input.GetKeyDown(KeyCode.C))
                {
                    manager.StartClient();
                }
            }
            if (NetworkServer.active && manager.IsClientConnected())
            {
                if (Input.GetKeyDown(KeyCode.X))
                {
                    manager.StopHost();
                }
            }
        }

        void OnGUI()
        {
            if (!showGUI)
                return;

            int xpos = 10 + offsetX;
            int ypos = 40 + offsetY;
            const int spacing = 24;

            bool noConnection = (manager.client == null || manager.client.connection == null ||
                                 manager.client.connection.connectionId == -1);

            if (!manager.IsClientConnected() && !NetworkServer.active && manager.matchMaker == null)
            {
                if (noConnection)
                {
                    if (UnityEngine.Application.platform != RuntimePlatform.WebGLPlayer)
                    {
                        if (GUI.Button(new Rect(xpos, ypos, 200, 20), "LAN Host(H)"))
                        {
                            manager.StartHost();
                        }
                        ypos += spacing;
                    }

                    if (GUI.Button(new Rect(xpos, ypos, 105, 20), "LAN Client(C)"))
                    {

                        manager.StartClient();
                    }

                    manager.networkAddress = GUI.TextField(new Rect(xpos + 100, ypos, 95, 20), manager.networkAddress);

                    //Getting the user selected player option from GUI so that it related object player should be instantiated
                    isVR = GUI.Toggle(new Rect(xpos + 100 + 100, ypos, 95, 20), isVR, "is VR set");
                     if(isVR){
                         GetComponent<NetworkManagerCustom2>().playerPrefabIndex = 1;
                     }
                     else {
                         GetComponent<NetworkManagerCustom2>().playerPrefabIndex = 0;
                     }
                    ypos += spacing;

                    if (UnityEngine.Application.platform == RuntimePlatform.WebGLPlayer)
                    {
                        // cant be a server in webgl build
                        GUI.Box(new Rect(xpos, ypos, 200, 25), "(  WebGL cannot be server  )");
                        ypos += spacing;
                    }
                    else
                    {
                        if (GUI.Button(new Rect(xpos, ypos, 200, 20), "LAN Server Only(S)"))
                        {
                            manager.StartServer();
                        }
                        ypos += spacing;
                    }
                }
                else
                {
                    GUI.Label(new Rect(xpos, ypos, 200, 20), "Connecting to " + manager.networkAddress + ":" + manager.networkPort + "..");
                    ypos += spacing;


                    if (GUI.Button(new Rect(xpos, ypos, 200, 20), "Cancel Connection Attempt"))
                    {
                        manager.StopClient();
                    }
                }
            }
            else
            {
                if (NetworkServer.active)
                {
                    string serverMsg = "Server: port=" + manager.networkPort;
                    if (manager.useWebSockets)
                    {
                        serverMsg += " (Using WebSockets)";
                    }
                    GUI.Label(new Rect(xpos, ypos, 300, 20), serverMsg);
                    ypos += spacing;
                }
                if (manager.IsClientConnected())
                {
                    GUI.Label(new Rect(xpos, ypos, 300, 20), "Client: address=" + manager.networkAddress + " port=" + manager.networkPort);
                    ypos += spacing;
                }
            }

            if (manager.IsClientConnected() && !ClientScene.ready)
            {
                if (GUI.Button(new Rect(xpos, ypos, 200, 20), "Client Ready"))
                {
                    ClientScene.Ready(manager.client.connection);

                    if (ClientScene.localPlayers.Count == 0)
                    {
                        ClientScene.AddPlayer(0);
                    }
                }
                ypos += spacing;
            }

            if (NetworkServer.active || manager.IsClientConnected())
            {
                if (GUI.Button(new Rect(xpos, ypos, 200, 20), "Stop (X)"))
                {
                    manager.StopHost();
                }
                ypos += spacing;
            }

            if (!NetworkServer.active && !manager.IsClientConnected() && noConnection)
            {
                ypos += 10;

                if (UnityEngine.Application.platform == RuntimePlatform.WebGLPlayer)
                {
                    GUI.Box(new Rect(xpos - 5, ypos, 220, 25), "(WebGL cannot use Match Maker)");
                    return;
                }

                if (manager.matchMaker == null)
                {
                    if (GUI.Button(new Rect(xpos, ypos, 200, 20), "Enable Match Maker (M)"))
                    {
                        manager.StartMatchMaker();
                    }
                    ypos += spacing;
                }
                else
                {
                    if (manager.matchInfo == null)
                    {
                        if (manager.matches == null)
                        {
                            if (GUI.Button(new Rect(xpos, ypos, 200, 20), "Create Internet Match"))
                            {
                                manager.matchMaker.CreateMatch(manager.matchName, manager.matchSize, true, "", "", "", 0, 0, manager.OnMatchCreate);
                            }
                            ypos += spacing;

                            GUI.Label(new Rect(xpos, ypos, 100, 20), "Room Name:");
                            manager.matchName = GUI.TextField(new Rect(xpos + 100, ypos, 100, 20), manager.matchName);
                            ypos += spacing;

                            ypos += 10;

                            if (GUI.Button(new Rect(xpos, ypos, 200, 20), "Find Internet Match"))
                            {
                                manager.matchMaker.ListMatches(0, 20, "", false, 0, 0, manager.OnMatchList);
                            }
                            ypos += spacing;
                        }
                        else
                        {
                            for (int i = 0; i < manager.matches.Count; i++)
                            {
                                var match = manager.matches[i];
                                if (GUI.Button(new Rect(xpos, ypos, 200, 20), "Join Match:" + match.name))
                                {
                                    manager.matchName = match.name;
                                    manager.matchMaker.JoinMatch(match.networkId, "", "", "", 0, 0, manager.OnMatchJoined);
                                }
                                ypos += spacing;
                            }

                            if (GUI.Button(new Rect(xpos, ypos, 200, 20), "Back to Match Menu"))
                            {
                                manager.matches = null;
                            }
                            ypos += spacing;
                        }
                    }

                    if (GUI.Button(new Rect(xpos, ypos, 200, 20), "Change MM server"))
                    {
                        m_ShowServer = !m_ShowServer;
                    }
                    if (m_ShowServer)
                    {
                        ypos += spacing;
                        if (GUI.Button(new Rect(xpos, ypos, 100, 20), "Local"))
                        {
                            manager.SetMatchHost("localhost", 1337, false);
                            m_ShowServer = false;
                        }
                        ypos += spacing;
                        if (GUI.Button(new Rect(xpos, ypos, 100, 20), "Internet"))
                        {
                            manager.SetMatchHost("mm.unet.unity3d.com", 443, true);
                            m_ShowServer = false;
                        }
                        ypos += spacing;
                        if (GUI.Button(new Rect(xpos, ypos, 100, 20), "Staging"))
                        {
                            manager.SetMatchHost("staging-mm.unet.unity3d.com", 443, true);
                            m_ShowServer = false;
                        }
                    }

                    ypos += spacing;

                    GUI.Label(new Rect(xpos, ypos, 300, 20), "MM Uri: " + manager.matchMaker.baseUri);
                    ypos += spacing;

                    if (GUI.Button(new Rect(xpos, ypos, 200, 20), "Disable Match Maker"))
                    {
                        manager.StopMatchMaker();
                    }
                    ypos += spacing;
                }
            }
        }
    }
}
#endif //ENABLE_UNET
    /**/
|improve this answer|||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.