which function to override

Hello Does anyone know which function i need to override to control the spawn behavior for the game player in network lobby manager. That is the game player not the lobby player. I want to be able to set a specific spawn location based on custom logic Thanks

After further investigation and looking at unet source, it seems the only way is to override this function: OnServerSceneChanged()

public override void OnServerSceneChanged(string sceneName)
        {
            if (sceneName != m_LobbyScene)
            {
                // call SceneLoadedForPlayer on any players that become ready while we were loading the scene.
                foreach (var pending in m_PendingPlayers)
                {
                    SceneLoadedForPlayer(pending.conn, pending.lobbyPlayer);
                }
                m_PendingPlayers.Clear();
            }

            OnLobbyServerSceneChanged(sceneName);
        }

This calls the function SceneLoadedForPlayer , which does the spawning, however the function SceneLoadedForPlayer is not override-able

void SceneLoadedForPlayer(NetworkConnection conn, GameObject lobbyPlayerGameObject)
        {
            var lobbyPlayer = lobbyPlayerGameObject.GetComponent<NetworkLobbyPlayer>();
            if (lobbyPlayer == null)
            {
                // not a lobby player.. dont replace it
                return;
            }

            if (LogFilter.logDebug) { Debug.Log("NetworkLobby SceneLoadedForPlayer scene:" + Application.loadedLevelName + " " + conn); }

            if (Application.loadedLevelName == m_LobbyScene)
            {
                // cant be ready in lobby, add to ready list
                PendingPlayer pending;
                pending.conn = conn;
                pending.lobbyPlayer = lobbyPlayerGameObject;
                m_PendingPlayers.Add(pending);
                return;
            }

            var controllerId = lobbyPlayerGameObject.GetComponent<NetworkIdentity>().playerControllerId;
            var gamePlayer = OnLobbyServerCreateGamePlayer(conn, controllerId);
            if (gamePlayer == null)
            {
                // get start position from base class

                Transform startPos = GetStartPosition();

                if (startPos != null)

                {

                    gamePlayer = (GameObject)Instantiate(gamePlayerPrefab, startPos.position, startPos.rotation);

                }
                else
                {
                    gamePlayer = (GameObject)Instantiate(gamePlayerPrefab, Vector3.zero, Quaternion.identity);
                }
            }

            if (!OnLobbyServerSceneLoadedForPlayer(lobbyPlayerGameObject, gamePlayer))
            {
                return;
            }

            // replace lobby player with game player
            NetworkServer.ReplacePlayerForConnection(conn, gamePlayer, controllerId);
     
        }
public Transform GetStartPosition()
        {
            // first remove any dead transforms
            if (s_StartPositions.Count > 0)
            {
                for (int i = s_StartPositions.Count - 1; i >= 0; i--)
                {
                    if (s_StartPositions[i] == null)
                        s_StartPositions.RemoveAt(i);
                }
            }

            if (m_PlayerSpawnMethod == PlayerSpawnMethod.Random && s_StartPositions.Count > 0)
            {
                // try to spawn at a random start location
                int index = Random.Range(0, s_StartPositions.Count);
                return s_StartPositions[index];
            }
            if (m_PlayerSpawnMethod == PlayerSpawnMethod.RoundRobin && s_StartPositions.Count > 0)
            {
                if (s_StartPositionIndex >= s_StartPositions.Count)
                {
                    s_StartPositionIndex = 0;
                }

                Transform startPos = s_StartPositions[s_StartPositionIndex];
                s_StartPositionIndex += 1;
                return startPos;
            }
            return null;
        }

This function basically gets its spawn position from GetStartPosition() which is a function in the base network manager class. In my opinion GetStartPosition() is a function which absolutely should have been overrideable so we can set our own spawn positions, from what i can tell i am going to have to prevent SceneLoadedForPlayer() from even running by making my own version of the top level function OnServerSceneChanged as this is the only one in this chain that i can override. I could be wrong, if someone knows a better way can you please mention it here?

thanks

okay so I’m trying to override OnServerSceneChanged, however i dont have access to the pending player list because its not a public variable. I cant just declare the list in my own function because various other functions in the base class use that list and unless i have public access to the actual list in the base class, id have to pretty much rewrite the entire NetworkLobbyManagerScript. Does anyone know of a better way, i shouldn’t have to work so hard to simply have custom spawning logic in lobby manager …

thanks

The lobby manager function have OnLobby* prefix. Use:

http://docs.unity3d.com/ScriptReference/Networking.NetworkLobbyManager.OnLobbyServerCreateGamePlayer.html

1 Like

Thanks for the reply @notseanr , however i am unsure about how to use it for changing the spawn position of my player. i have however had limited success with this

        public override bool OnLobbyServerSceneLoadedForPlayer(GameObject lobbyPlayer, GameObject gamePlayer)
        {
            GameObject SpawnPoint = GameObject.FindGameObjectWithTag("SpawnTeamOne");
            //var gamePlayer = OnLobbyServerCreateGamePlayer(conn, controllerId);
            gamePlayer.transform.position = SpawnPoint .transform.position;

            return true;
        }

However this only works with the host, and all clients dont seem to get moved after spawning. Do i need to somehow use an RPC (or whatever its called these days) with this?

regards

i am still stuck with this, if anyone could help it would be great. its taking me way too long to do something which should have been clearly documented. I am not a new programmer as well, which just shows how complex this system is.

regards

okay so i figured it out, turns out notseanr pointed me in the right direction, it was just super confusing and i still cant believe they chose to do it like this. So it turns out what unity does internally is it checks the return state from OnLobbyServerCreateGamePlayer. if it returns null, it goes ahead and continues with its own logic, however if you spawn something yourself and the function wont return null and therefore it wont execute its own set of spawning and moving things around… I hope this helps someone else, below is my final code.

 public override GameObject OnLobbyServerCreateGamePlayer(NetworkConnection conn, short playerControllerId)
  {

  GameObject myPlayer;
  GameObject spawnpos= GameObject.FindGameObjectWithTag("spawnpos");

  myPlayer = Instantiate(gamePlayerPrefab, spawnpos.transform.position, Quaternion.identity) as GameObject;

  return myPlayer;
  }