Home > Back-end >  after spawn player are swapping places
after spawn player are swapping places

Time:12-26

I am creating a multiplayer game in webGL and in my network manager script i am storing and spawning players. after build in the WebGL player spawning but swapping their places. i have only two player. one player spwan and when second spwanit swap the place of 1st one. here is the code.

 [Header("Spawn Points")]
        public Transform[] spawnPoints; //stores the spawn points
  public void EmitJoin()
        {
           // PopupOpenerCaptureClick();
            //hash table <key, value>
            Dictionary<string, string> data = new Dictionary<string, string>();


            //send the position point to server
            string msg = string.Empty;


            data["name"] = CanvasManager.instance.inputLogin.text;

            data["publicAddress"] = "none";

            if (onLoggedWithMetamask)
            {
                data["publicAddress"] = CanvasManager.instance.myPublicAdrr;
            }

            //store player's skin
            data["model"] = CharacterChoiceManager.instance.current_model.ToString();
            data["posX"] = spawnPoints[0].position.x.ToString();
            data["posY"] = spawnPoints[0].position.y.ToString();
            data["posZ"] = spawnPoints[0].position.z.ToString();

            //sends to the nodejs server through socket the json package
            Application.ExternalCall("socket.emit", "JOIN", new JSONObject(data));

            //obs: take a look in server script.
        }
 void OnSpawnPlayer(string data)
        {

            /*
             * pack[0] = id (network player id)
             * pack[1]= name
             * pack[3] = position.x
             * pack[4] = position.y
             * pack[5] = position.z
            */

            var pack = data.Split(Delimiter);

            bool alreadyExist = false;

            //verify all players to avoid duplicates 
            if (networkPlayers.ContainsKey(pack[0]))
            {
                alreadyExist = true;
            }
            if (!alreadyExist)
            {
                Debug.Log("received spawn network player");





                PlayerManager newPlayer;

                if (networkPlayers.Count > 0)
                {
                    // newPlayer = GameObject.Instantiate( network player avatar or model, spawn position, spawn rotation)
                    newPlayer = GameObject.Instantiate(playerPref,
                            spawnPoints[0].position, spawnPoints[0].transform.rotation).GetComponent<PlayerManager>();

                }
                else
                {
                    // newPlayer = GameObject.Instantiate( network player avatar or model, spawn position, spawn rotation)
                    newPlayer = GameObject.Instantiate(playerPref,
                            spawnPoints[1].position, spawnPoints[1].transform.rotation).GetComponent<PlayerManager>();
                }




                Debug.Log("player spawned");

               
            }


        }

I have tried to change the array of spwan points but same result.caqn someone tell me why they swapping their places.

CodePudding user response:

I am not certain, but I think I know your issue and a possible solution to it.

The problem

Let's take a situation where player A has joined and he is waiting...

So the problem is that when player B joins, your player A scene recieves (from the network) a new prefab containing a new camera, player movements, etc.

If this is the case, your player A will take control of the new prefab. If not, then the problem has to do with your code which we haven't seen yet.

*For player B, I am not entirely sure why he taking player A point of view.

Solution

If your problem is the same as described above, then the fix would be to make sure only 1 gameObject contains a camera and player scripts.

So if player B joins, then player A simply recieves an "empty" prefab from scripts. The positions, animations, etc. of player B will be managed by the network from player A perspective.


If this doesn't help, then give some feedback or more code related to your problem.

Good luck!

CodePudding user response:

Here is the Screen shot of Prefab

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Text.RegularExpressions;
using System.Text;
using UnityEngine.UI;
using System.Runtime.InteropServices;
using Cinemachine;
using TMPro;


/// <summary>
/// Network Manager class.
/// </summary>
///
namespace MetaverseSample
{
    public class NetworkManager : MonoBehaviour
    {


        public static NetworkManager instance; //useful for any gameObject to access this class without the need of instances her or you declare it

        static private readonly char[] Delimiter = new char[] { ':' };    //Variable that defines ':' character as separator

        [HideInInspector]
        public bool onLogged = false; //flag which is determined the player is logged in the game arena


        [HideInInspector]
        public bool onLoggedWithMetamask = false; //flag which is determined the player is logged in the game arena

        [HideInInspector]
        public GameObject localPlayer; //store localPlayer

        [HideInInspector]
        public string local_player_id;

        //store all players in game
        public Dictionary<string, PlayerManager> networkPlayers = new Dictionary<string, PlayerManager>();

        [Header("Local Player Prefab")]
        public GameObject playerPref; //store the local player prefabs


        [Header("Spawn Points")]
        public Transform[] spawnPoints; //stores the spawn points

        [Header("Camera Rig Prefab")]
      //  public GameObject camRigPref;

        [HideInInspector]
       // public GameObject camRig;

        [Header("Cinemachine Camera")]
      //  public CinemachineFreeLook cinemachineFreeLook;

        [Header("Field Of View Variables")]
        public float defaultFOV;

        [HideInInspector]
        public bool isGameOver; // game over flag

        [HideInInspector]
        public string _inputAxisNameX;

        [HideInInspector]
        public string _inputAxisNameY;

        public string account;

        [DllImport("__Internal")] private static extern void MetamaskSignIn();

        [DllImport("__Internal")] private static extern void ConfirmTransaction(string _amount);

      //  [DllImport("__Internal")] private static extern void PopupOpenerCaptureClick();



        void Awake()
        {
            Application.ExternalEval("socket.isReady = true;");

           // _inputAxisNameX = cinemachineFreeLook.m_XAxis.m_InputAxisName;
           // _inputAxisNameY = cinemachineFreeLook.m_YAxis.m_InputAxisName;

        }

        // Use this for initialization
        void Start()
        {

            // if don't exist an instance of this class
            if (instance == null)
            {


                //it doesn't destroy the object, if other scene be loaded
                DontDestroyOnLoad(this.gameObject);
                instance = this;// define the class as a static variable


                Debug.Log("start mmo game");



            }
            else
            {
                //it destroys the class if already other class exists
                Destroy(this.gameObject);
            }

        }



        /// <summary>
        /// Prints the pong message which arrived from server.
        /// </summary>
        /// <param name="_msg">Message.</param>
        public void OnPrintPongMsg(string data)
        {

            /*
             * data.pack[0]= msg
            */

            var pack = data.Split(Delimiter);
            Debug.Log("received message: "   pack[0]   " from server by callbackID: PONG");
        }

        // <summary>
        /// sends ping message to server.
        /// </summary>
        public void EmitPing()
        {

            //hash table <key, value>
            Dictionary<string, string> data = new Dictionary<string, string>();

            //store "ping!!!" message in msg field
            data["msg"] = "ping!!!!";

            JSONObject jo = new JSONObject(data);

            //sends to the nodejs server through socket the json package
            Application.ExternalCall("socket.emit", "PING", new JSONObject(data));


        }



        // <summary>
        /// manages and switches user login.
        /// </summary>
        public void SignIn(string _method)
        {

            switch (_method)
            {
                case "metamask":
                    MetamaskSignIn();
                    break;
                case "guest":
                    CanvasManager.instance.OpenScreen(2);
                    break;
            }

        }






        //call be  OnClickJoinBtn() method from CanvasManager class
        /// <summary>
        /// Emits the player's information to the server.
        /// </summary>
        /// <param name="_login">Login.</param>
        public void EmitJoin()
        {
           // PopupOpenerCaptureClick();
            //hash table <key, value>
            Dictionary<string, string> data = new Dictionary<string, string>();


            //send the position point to server
            string msg = string.Empty;


            data["name"] = CanvasManager.instance.inputLogin.text;

            data["publicAddress"] = "none";

            if (onLoggedWithMetamask)
            {
                data["publicAddress"] = CanvasManager.instance.myPublicAdrr;
            }

            //store player's skin
            data["model"] = CharacterChoiceManager.instance.current_model.ToString();
            data["posX"] = spawnPoints[0].position.x.ToString();
            data["posY"] = spawnPoints[0].position.y.ToString();
            data["posZ"] = spawnPoints[0].position.z.ToString();

            //sends to the nodejs server through socket the json package
            Application.ExternalCall("socket.emit", "JOIN", new JSONObject(data));

            //obs: take a look in server script.
        }

        /// <summary>
        /// Joins the local player in game.
        /// </summary>
        /// <param name="_data">Data.</param>
        public void OnJoinGame(string data)
        {


            /*
             * pack[0] = id (local player id)
             * pack[1]= name (local player name)
             * pack[2] = position.x (local player position x)
             * pack[3] = position.y (local player position ...)
             * pack[4] = model

            */

            Debug.Log("Login successful, joining game");

            var pack = data.Split(Delimiter);

            // the local player now is logged
            onLogged = true;

            // take a look in NetworkPlayer.cs script
            PlayerManager newPlayer;

            if (networkPlayers.Count > 0)
            {
                newPlayer = GameObject.Instantiate(playerPref,
                spawnPoints[0].position, spawnPoints[0].transform.rotation).GetComponent<PlayerManager>();

            }
            else
            {
                newPlayer = GameObject.Instantiate(playerPref,
                spawnPoints[1].position, spawnPoints[1].transform.rotation).GetComponent<PlayerManager>();
            }





            Debug.Log("player instantiated");

            account = pack[0];

            newPlayer.id = pack[0];

            //this is local player
            newPlayer.isLocalPlayer = true;

            //now local player online in the arena
            newPlayer.isOnline = true;

            //set local player's 3D text with his name
            newPlayer.Set3DName(pack[1]);

            //puts the local player on the list
            networkPlayers[pack[0]] = newPlayer;

            localPlayer = networkPlayers[pack[0]].gameObject;

            local_player_id = pack[0];

            //spawn camRigPref from Standard Assets\Cameras\Prefabs\MultipurposeCameraRig.prefab
          //  camRig = GameObject.Instantiate(camRigPref, new Vector3(0f, 0f, 0f), Quaternion.identity);

           // SetCinemachineFreeLookTarget(newPlayer.models[int.Parse(pack[5])].transform);
            //cinemachineFreeLook.m_Lens.FieldOfView = defaultFOV;

            newPlayer.SetModel(int.Parse(pack[5]));

            //hide the lobby menu (the input field and join buton)
            CanvasManager.instance.OpenScreen(1);
            CharacterChoiceManager.instance.HideModels();
            Debug.Log("player in game");

        }


        public void SetCinemachineFreeLookTarget(Transform _target)
        {

          //  cinemachineFreeLook.LookAt = _target;

          //  cinemachineFreeLook.Follow = _target;



        }

        /// <summary>
        /// Raises the spawn player event.
        /// </summary>
        /// <param name="_msg">Message.</param>
        void OnSpawnPlayer(string data)
        {

            /*
             * pack[0] = id (network player id)
             * pack[1]= name
             * pack[3] = position.x
             * pack[4] = position.y
             * pack[5] = position.z
            */

            var pack = data.Split(Delimiter);

            bool alreadyExist = false;

            //verify all players to avoid duplicates 
            if (networkPlayers.ContainsKey(pack[0]))
            {
                alreadyExist = true;
            }
            if (!alreadyExist)
            {
                Debug.Log("received spawn network player");





                PlayerManager newPlayer;

                if (networkPlayers.Count > 0)
                {
                    // newPlayer = GameObject.Instantiate( network player avatar or model, spawn position, spawn rotation)
                    newPlayer = GameObject.Instantiate(playerPref,
                            spawnPoints[0].position, spawnPoints[0].transform.rotation).GetComponent<PlayerManager>();

                }
                else
                {
                    // newPlayer = GameObject.Instantiate( network player avatar or model, spawn position, spawn rotation)
                    newPlayer = GameObject.Instantiate(playerPref,
                            spawnPoints[1].position, spawnPoints[1].transform.rotation).GetComponent<PlayerManager>();
                }




                Debug.Log("player spawned");

                newPlayer.id = pack[0];

                newPlayer.name = pack[1];

                newPlayer.isLocalPlayer = false; //it is not the local player

                newPlayer.isOnline = true; //set network player online in the arena

                newPlayer.Set3DName(pack[1]); //set the network player 3D text with his name

                newPlayer.gameObject.name = pack[0];

                newPlayer.SetModel(int.Parse(pack[5]));

                networkPlayers[pack[0]] = newPlayer; //puts the network player on the list
            }


        }





        /// <summary>
        /// send player's position and rotation to the server
        /// </summary>
        /// <param name="data"> package with player's position and rotation</param>
        public void EmitMoveAndRotate(Dictionary<string, string> data)
        {

            JSONObject jo = new JSONObject(data);

            //sends to the nodejs server through socket the json package
            Application.ExternalCall("socket.emit", "MOVE_AND_ROTATE", new JSONObject(data));

        }



        /// <summary>
        /// Update the network player position and rotation to local player.
        /// </summary>
        /// <param name="_msg">Message.</param>
        void OnUpdateMoveAndRotate(string data)
        {
            /*
             * data.pack[0] = id (network player id)
             * data.pack[1] = position.x
             * data.pack[2] = position.y
             * data.pack[3] = position.z
             * data.pack[4] = "rotation.y"
            */

            Debug.Log("received pos and rot");

            var pack = data.Split(Delimiter);

            if (networkPlayers.ContainsKey(pack[0]))
            {

                PlayerManager netPlayer = networkPlayers[pack[0]];

                //update with the new position
                netPlayer.UpdatePosition(new Vector3(
                    UtilsClass.StringToFloat(pack[1]), UtilsClass.StringToFloat(pack[2]), UtilsClass.StringToFloat(pack[3])));

                //update new player rotation
                netPlayer.UpdateRotation(new Quaternion(netPlayer.transform.rotation.x, UtilsClass.StringToFloat(pack[4]),
                netPlayer.transform.rotation.z, netPlayer.transform.rotation.w));

            }


        }



        /// <summary>
        /// Emits the local player animation to Server.js.
        /// </summary>
        /// <param name="_animation">animation's name.</param>
        public void EmitAnimation(string _animation)
        {
            //hash table <key, value>
            Dictionary<string, string> data = new Dictionary<string, string>();

            data["local_player_id"] = localPlayer.GetComponent<PlayerManager>().id;

            data["animation"] = _animation;

            JSONObject jo = new JSONObject(data);

            //sends to the nodejs server through socket the json package
            Application.ExternalCall("socket.emit", "ANIMATION", new JSONObject(data));


        }

        /// <summary>
        ///  Update the network player animation to local player.
        /// </summary>
        /// <param name="data">package received from server with player id and  animation's name</param>
        void OnUpdateAnim(string data)
        {
            /*
             * data.pack[0] = id (network player id)
             * data.pack[1] = animation (network player animation)
            */

            var pack = data.Split(Delimiter);

            //find network player by your id
            PlayerManager netPlayer = networkPlayers[pack[0]];

            //updates current animation
            netPlayer.UpdateAnimator(pack[1]);

        }



        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////// USERS LIST UPDATES/////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////


        public void EmitGetUsersList()
        {

            CanvasManager.instance.ClearUsersList();

            //sends to the nodejs server through socket the json package
            Application.ExternalCall("socket.emit", "GET_USERS_LIST");


        }

        void OnClearUsersList()
        {
            CanvasManager.instance.ClearUsersList();
        }

        void OnUpdateUsersList(string data)
        {

            /*
             * pack[0] = id
             * pack[1] = name
             * pack[2] = public address
            */

            var pack = data.Split(Delimiter);


            //Debug.Log("received best players from server ...");
            //Debug.Log("id: " pack[0]);
            //Debug.Log("name: " pack[1]);
            //Debug.Log("public address: " pack[2]);

            CanvasManager.instance.SetUpUser(pack[0], pack[1], pack[2]);

        }
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////



        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //////////////////////////////////////////////MESSAGE FUNCTIONS////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// method to emit message to the server.
        /// </summary>
        public void EmitMessage()
        {
            Dictionary<string, string> data = new Dictionary<string, string>();

            string msg = string.Empty;

            //Identifies with the name "MESSAGE", the notification to be transmitted to the server
            data["callback_name"] = "MESSAGE";

            data["id"] = local_player_id;

            data["message"] = CanvasManager.instance.inputFieldMessage.text;

            CanvasManager.instance.inputFieldMessage.text = string.Empty;


            //sends to the nodejs server through socket the json package
            Application.ExternalCall("socket.emit", data["callback_name"], new JSONObject(data));


        }

        /// <summary>
        /// method to handle notification that arrived from the server.
        /// </summary>  
        /// <param name="data">received package from server.</param>
        void OnReceiveMessage(string data)
        {

            /*
                 * data.pack[0] = id (network player id)
                 * data.pack[1]= message
                */



            var pack = data.Split(Delimiter);


            if (local_player_id.Equals(pack[0]))
            {

                CanvasManager.instance.SpawnMyMessage(pack[1]);

            }
            else
            {
                CanvasManager.instance.SpawnNetworkMessage(networkPlayers[pack[0]].name, pack[1]);
            }


        }



        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //////////////////////////////////////////////PRIVATE CHAT FUNCTIONS////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////


        /// <summary>
        /// method to emit message to the server.
        /// </summary>
        public void EmitOpenChatBox(string _player_id)
        {
            Dictionary<string, string> data = new Dictionary<string, string>();

            string msg = string.Empty;

            //Identifies with the name "MESSAGE", the notification to be transmitted to the server
            data["callback_name"] = "SEND_OPEN_CHAT_BOX";

            data["player_id"] = _player_id;

            //sends to the nodejs server through socket the json package
            Application.ExternalCall("socket.emit", data["callback_name"], new JSONObject(data));


        }


        /// <summary>
        /// method to handle notification that arrived from the server.
        /// </summary>  
        /// <param name="data">received package from server.</param>
        void OnReceiveOpenChatBox(string data)
        {

            /*
                 * data.pack[0] = host id 
                 * data.pack[1]= guest id
                */



            var pack = data.Split(Delimiter);

            if (local_player_id.Equals(pack[0]))
            {
                //spawn new chatbox
                CanvasManager.instance.SpawnChatBox(pack[0], pack[0], pack[1], networkPlayers[pack[1]].name);

            }
            else
            {
                CanvasManager.instance.SpawnChatBox(pack[0], pack[1], pack[0], networkPlayers[pack[0]].name);


            }


        }


        /// <summary>
        /// method to emit message to the server.
        /// </summary>
        public void EmitPrivateMessage(string _message, string _chat_box_id, string _gest_id)
        {
            Dictionary<string, string> data = new Dictionary<string, string>();

            string msg = string.Empty;

            //Identifies with the name "MESSAGE", the notification to be transmitted to the server
            data["callback_name"] = "PRIVATE_MESSAGE";

            data["chat_box_id"] = _chat_box_id;

            data["guest_id"] = _gest_id;

            data["message"] = _message;

            CanvasManager.instance.inputFieldPrivateMessage.text = string.Empty;


            //sends to the nodejs server through socket the json package
            Application.ExternalCall("socket.emit", data["callback_name"], new JSONObject(data));


        }

        /// <summary>
        /// method to handle notification that arrived from the server.
        /// </summary>  
        /// <param name="data">received package from server.</param>
        void OnReceivePrivateMessage(string data)
        {

            /*
                 * data.pack[0] = guest (network player id)
                 * data.pack[1]= message
                */



            var pack = data.Split(Delimiter);

            Debug.Log("pack[0]: "   pack[0]);
            Debug.Log("pack[1]: "   pack[1]);
            Debug.Log("pack[2]: "   pack[2]);

            if (CanvasManager.instance.chatBoxes.ContainsKey(pack[0]))
            {
                if (local_player_id.Equals(pack[1]))
                {


                    CanvasManager.instance.chatBoxes[pack[0]].SpawnMyMessage(pack[2]);

                }
                else
                {
                    CanvasManager.instance.chatBoxes[pack[0]].SpawnNetworkMessage(pack[2]);
                }
            }


        }

        /// <summary>
        /// method to emit message to the server.
        /// </summary>
        public void EmitConfirmTransaction(string _id_to, string _amount)
        {
            Dictionary<string, string> data = new Dictionary<string, string>();

            string msg = string.Empty;

            //Identifies with the name "MESSAGE", the notification to be transmitted to the server
            data["callback_name"] = "CONFIRM_TRANSACTION";

            data["idTo"] = _id_to;

            data["amount"] = _amount;

            //sends to the nodejs server through socket the json package
            Application.ExternalCall("socket.emit", data["callback_name"], new JSONObject(data));


        }

        void OnConfirmTransaction(string data)
        {

            /*
             * data.pack[0] = amount

            */

            var pack = data.Split(Delimiter);

            Debug.Log("amount: "   pack[0]);

            ConfirmTransaction(pack[0]);


        }


        void OnUpdateUserVoiceInfo(string data)
        {

            /*
             * data.pack[0] = id

            */

            var pack = data.Split(Delimiter);

            //Debug.Log("name: " networkPlayers[pack[0]].name);

            CanvasManager.instance.if_CurrentUserNameVoice.text = networkPlayers[pack[0]].name   " is talking";

            StartCoroutine("ClearCurrentVoiceText");




        }


        IEnumerator ClearCurrentVoiceText()
        {

            yield return new WaitForSeconds(3f); // wait for set reload time

            CanvasManager.instance.if_CurrentUserNameVoice.text = string.Empty;


        }

        /// <summary>
        /// method to emit message to the server.
        /// </summary>
        public void EmitMuteAllUsers()
        {

            Dictionary<string, string> data = new Dictionary<string, string>();

            //Identifies with the name "MESSAGE", the notification to be transmitted to the server
            data["callback_name"] = "MUTE_ALL_USERS";

            //sends to the nodejs server through socket the json package
            Application.ExternalCall("socket.emit", data["callback_name"]);


        }

        /// Emits the local player mute request  to Server.js.
        /// </summary>
        public void EmitAudioMute()
        {

            //sends to the nodejs server through socket the json package
            Application.ExternalCall("socket.emit", "AUDIO_MUTE");


        }





        /// <summary>
        /// method to emit message to the server.
        /// </summary>
        public void EmitRemoveAllUsersMute()
        {

            Dictionary<string, string> data = new Dictionary<string, string>();

            //Identifies with the name "MESSAGE", the notification to be transmitted to the server
            data["callback_name"] = "REMOVE_MUTE_ALL_USERS";

            //sends to the nodejs server through socket the json package
            Application.ExternalCall("socket.emit", data["callback_name"]);


        }


        /// <summary>
        /// method to emit message to the server.
        /// </summary>
        public void EmitMuteUser(string _id)
        {
            Dictionary<string, string> data = new Dictionary<string, string>();

            string msg = string.Empty;

            //Identifies with the name "MESSAGE", the notification to be transmitted to the server
            data["callback_name"] = "ADD_MUTE_USER";

            data["id"] = _id;

            //sends to the nodejs server through socket the json package
            Application.ExternalCall("socket.emit", data["callback_name"], new JSONObject(data));


        }

        /// <summary>
        /// method to emit message to the server.
        /// </summary>
        public void EmitRemoveMuteUser(string _id)
        {
            Dictionary<string, string> data = new Dictionary<string, string>();

            string msg = string.Empty;

            //Identifies with the name "MESSAGE", the notification to be transmitted to the server
            data["callback_name"] = "REMOVE_MUTE_USER";

            data["id"] = _id;

            //sends to the nodejs server through socket the json package
            Application.ExternalCall("socket.emit", data["callback_name"], new JSONObject(data));


        }




        /// <summary>
        /// inform the local player to destroy offline network player
        /// </summary>
        /// <param name="_msg">Message.</param>
        //desconnect network player
        void OnUserDisconnected(string data)
        {

            /*
             * data.pack[0] = id (network player id)
            */

            var pack = data.Split(Delimiter);


            if (networkPlayers.ContainsKey(pack[0]))
            {


                //destroy network player by your id
                Destroy(networkPlayers[pack[0]].gameObject);


                //remove from the dictionary
                networkPlayers.Remove(pack[0]);

            }

        }


    }
}

  • Related