Search Unity

which function to override

Discussion in 'Multiplayer' started by Zero123, Mar 11, 2016.

  1. Zero123

    Zero123

    Joined:
    Aug 31, 2014
    Posts:
    23
    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
     
  2. Zero123

    Zero123

    Joined:
    Aug 31, 2014
    Posts:
    23
    After further investigation and looking at unet source, it seems the only way is to override this function: OnServerSceneChanged()


    Code (CSharp):
    1. public override void OnServerSceneChanged(string sceneName)
    2.         {
    3.             if (sceneName != m_LobbyScene)
    4.             {
    5.                 // call SceneLoadedForPlayer on any players that become ready while we were loading the scene.
    6.                 foreach (var pending in m_PendingPlayers)
    7.                 {
    8.                     SceneLoadedForPlayer(pending.conn, pending.lobbyPlayer);
    9.                 }
    10.                 m_PendingPlayers.Clear();
    11.             }
    12.  
    13.             OnLobbyServerSceneChanged(sceneName);
    14.         }


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



    Code (CSharp):
    1. void SceneLoadedForPlayer(NetworkConnection conn, GameObject lobbyPlayerGameObject)
    2.         {
    3.             var lobbyPlayer = lobbyPlayerGameObject.GetComponent<NetworkLobbyPlayer>();
    4.             if (lobbyPlayer == null)
    5.             {
    6.                 // not a lobby player.. dont replace it
    7.                 return;
    8.             }
    9.  
    10.             if (LogFilter.logDebug) { Debug.Log("NetworkLobby SceneLoadedForPlayer scene:" + Application.loadedLevelName + " " + conn); }
    11.  
    12.             if (Application.loadedLevelName == m_LobbyScene)
    13.             {
    14.                 // cant be ready in lobby, add to ready list
    15.                 PendingPlayer pending;
    16.                 pending.conn = conn;
    17.                 pending.lobbyPlayer = lobbyPlayerGameObject;
    18.                 m_PendingPlayers.Add(pending);
    19.                 return;
    20.             }
    21.  
    22.             var controllerId = lobbyPlayerGameObject.GetComponent<NetworkIdentity>().playerControllerId;
    23.             var gamePlayer = OnLobbyServerCreateGamePlayer(conn, controllerId);
    24.             if (gamePlayer == null)
    25.             {
    26.                 // get start position from base class
    27.  
    28.                 Transform startPos = GetStartPosition();
    29.  
    30.                 if (startPos != null)
    31.  
    32.                 {
    33.  
    34.                     gamePlayer = (GameObject)Instantiate(gamePlayerPrefab, startPos.position, startPos.rotation);
    35.  
    36.                 }
    37.                 else
    38.                 {
    39.                     gamePlayer = (GameObject)Instantiate(gamePlayerPrefab, Vector3.zero, Quaternion.identity);
    40.                 }
    41.             }
    42.  
    43.             if (!OnLobbyServerSceneLoadedForPlayer(lobbyPlayerGameObject, gamePlayer))
    44.             {
    45.                 return;
    46.             }
    47.  
    48.             // replace lobby player with game player
    49.             NetworkServer.ReplacePlayerForConnection(conn, gamePlayer, controllerId);
    50.      
    51.         }



    Code (CSharp):
    1. public Transform GetStartPosition()
    2.         {
    3.             // first remove any dead transforms
    4.             if (s_StartPositions.Count > 0)
    5.             {
    6.                 for (int i = s_StartPositions.Count - 1; i >= 0; i--)
    7.                 {
    8.                     if (s_StartPositions[i] == null)
    9.                         s_StartPositions.RemoveAt(i);
    10.                 }
    11.             }
    12.  
    13.             if (m_PlayerSpawnMethod == PlayerSpawnMethod.Random && s_StartPositions.Count > 0)
    14.             {
    15.                 // try to spawn at a random start location
    16.                 int index = Random.Range(0, s_StartPositions.Count);
    17.                 return s_StartPositions[index];
    18.             }
    19.             if (m_PlayerSpawnMethod == PlayerSpawnMethod.RoundRobin && s_StartPositions.Count > 0)
    20.             {
    21.                 if (s_StartPositionIndex >= s_StartPositions.Count)
    22.                 {
    23.                     s_StartPositionIndex = 0;
    24.                 }
    25.  
    26.                 Transform startPos = s_StartPositions[s_StartPositionIndex];
    27.                 s_StartPositionIndex += 1;
    28.                 return startPos;
    29.             }
    30.             return null;
    31.         }
    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
     
  3. Zero123

    Zero123

    Joined:
    Aug 31, 2014
    Posts:
    23
    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
     
  4. notseanr

    notseanr

    Joined:
    Jan 15, 2016
    Posts:
    22
    Zero123 likes this.
  5. Zero123

    Zero123

    Joined:
    Aug 31, 2014
    Posts:
    23
    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

    Code (CSharp):
    1.         public override bool OnLobbyServerSceneLoadedForPlayer(GameObject lobbyPlayer, GameObject gamePlayer)
    2.         {
    3.             GameObject SpawnPoint = GameObject.FindGameObjectWithTag("SpawnTeamOne");
    4.             //var gamePlayer = OnLobbyServerCreateGamePlayer(conn, controllerId);
    5.             gamePlayer.transform.position = SpawnPoint .transform.position;
    6.  
    7.             return true;
    8.         }
    9.  
    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
     
  6. Zero123

    Zero123

    Joined:
    Aug 31, 2014
    Posts:
    23
    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
     
  7. Zero123

    Zero123

    Joined:
    Aug 31, 2014
    Posts:
    23
    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.

    Code (CSharp):
    1.  public override GameObject OnLobbyServerCreateGamePlayer(NetworkConnection conn, short playerControllerId)
    2.   {
    3.  
    4.   GameObject myPlayer;
    5.   GameObject spawnpos= GameObject.FindGameObjectWithTag("spawnpos");
    6.  
    7.   myPlayer = Instantiate(gamePlayerPrefab, spawnpos.transform.position, Quaternion.identity) as GameObject;
    8.  
    9.   return myPlayer;
    10.   }