Search Unity

Weird behavriour

Discussion in 'Multiplayer' started by Ekivenum, Nov 2, 2018.

  1. Ekivenum

    Ekivenum

    Joined:
    Jan 16, 2018
    Posts:
    8
    Hello everyone,

    I need help, something weird is happening, i can't explain, because it's not logical.

    please, check my code and tell me what is happening. Before i must explain some things:

    -I spawn heroe's when players are connected with this methode from NetworkPlayer

    Code (CSharp):
    1.     [Server]
    2.     protected void AddClientToServer()
    3.     {
    4.         m_NetManager.serverPlayersReadied -= AddClientToServer;
    5.  
    6.         if (isServer)
    7.         {
    8.             m_NetManager.ClearAllReadyStates();
    9.         }
    10.         Debug.Log("AddClientToServer", this);
    11.  
    12.         GameObject heroObject = Instantiate(m_HeroPrefab);
    13.         NetworkServer.SpawnWithClientAuthority(heroObject, connectionToClient);
    14.  
    15.         HeroManager heroManager = heroObject.GetComponent<HeroManager>();
    16.         heroManager.SetPlayerId(playerID);
    17.  
    18.         if (lateSetupOfClientPlayer)
    19.         {
    20.             lateSetupOfClientPlayer = false;
    21.             PoolManager.InstanceSet -= AddClientToServer;
    22.         }
    23.     }
    Everything is fine there.

    Then players can spawn "agents" with this method from networkPlayer

    Code (CSharp):
    1.     /// <summary>
    2.     /// Will spawn the unit from pool manager regarding the parameters
    3.     /// </summary>
    4.     /// <param name="agentIndex">reference for the agent prefab search</param>
    5.     [Command]
    6.     private void CmdSpawnAgentFromPool(int agentIndex)
    7.     {
    8.         Debug.Log("player " + this.GetComponent<NetworkIdentity>().netId, this);
    9.         PoolObject netPool = PoolManager.Instance.poolDictionnary[CompleteUnit];
    10.         GameObject go = netPool.GetFromPool();
    11.  
    12.         NetworkServer.Spawn(go);
    13.  
    14.         UnitManager unitManager = go.GetComponent<UnitManager>();
    15.         unitManager.SetIndexAndID(agentIndex, playerID);
    16.  
    17.         if (isServer)
    18.         {
    19.             AgentTypeDefinition agent = AgentsSelectedManager.Instance.agentsSelected[agentIndex];
    20.             AnalyticsHelper.PlayerUsedUnitInGame(agent.m_AgentName);
    21.         }
    22.     }

    So agents and heroes have, respectively, an UnitManager script and an HeroManager script( child class from UnitManager). For heroes as for agents i set a hooked variables like this :

    hero
    HeroManager heroManager = heroObject.GetComponent<HeroManager>();
    heroManager.SetPlayerId(playerID);

    agent
    UnitManager unitManager = go.GetComponent<UnitManager>();
    unitManager.SetIndexAndID(agentIndex, playerID);

    This call this code in UnitManager:

    Code (CSharp):
    1. public class UnitManager : NetworkBehaviour
    2. {
    3.     /// <summary>
    4.     /// Synced player ID, -1 means it has not changed yet (as the lowest valid player id is 0)
    5.     /// </summary>
    6.     [SyncVar(hook = "OnPlayerIdChanged")]
    7.     protected int m_PlayerId = -1;
    8.  
    9.     /// <summary>
    10.     /// Synced player agent choice, -1 means it has not changed yet (as the lowest valid agent index is 0)
    11.     /// </summary>
    12.     [SyncVar(hook = "OnAgentIndexChange")]
    13.     protected int m_AgentIndex = -1;
    14.  
    15.     #region SYNCVAR HOOKS
    16.     //sync var hooks that call their corresponding events
    17.     private void OnPlayerIdChanged(int playerId)
    18.     {
    19.         Debug.Log("OnPlayerIdChanged " + playerId, this);
    20.         this.m_PlayerId = playerId;
    21.         Initialize();
    22.     }
    23.  
    24.     private void OnAgentIndexChange(int index)
    25.     {
    26.         Debug.Log("OnAgentIndexChange " + index, this);
    27.         this.m_AgentIndex = index;
    28.     }
    29.     #endregion
    30.  
    31.  
    32.     #region Networking
    33.     [Server]
    34.     public void SetPlayerId(int id)
    35.     {
    36.         m_PlayerId = id;
    37.         Debug.Log("SetPlayerIdserver " + id, this);
    38.     }
    39.  
    40.     [Server]
    41.     public void SetIndexAndID(int index, int id)
    42.     {
    43.         m_AgentIndex = index;
    44.         m_PlayerId = id;
    45.  
    46.         Debug.Log("SetIndexAndID " + index +" " + id, this);
    47.  
    48.     }
    49.  
    50.     #endregion
    Here is the debug logs on host, you will seen the spawn of heroes
    hero-host.jpg
    and for client:
    hero client.jpg
    So there, everything is going well, i have the two heroes on both screens with correct variables.



    Now when i hit a button to spawn an agent, there it is:

    host is fine:
    agent host.jpg

    but on client, well this is weird:
    agent client.jpg


    You can see that only one variable "playerID" is sync with an hook, but not for agentIndex..
    How can it be possible?

    on both scenes the agents have the same netID. What is strange is that only one of two variable synchronize
    And why the OnPlayerIdChanged() debug.log is visible before SetPlayerID() ???
     
    Last edited: Nov 2, 2018
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Care to show more info regarding your argument out of range exception? I'd guess that is key to your issues. And what does Initialize() do? Does it assume m_AgentIndex is already set?

    SyncVars do not update to clients immediately when updated on the server, so the order you update them does not necessarily result in the order they are updated on the client.
     
    Last edited: Nov 5, 2018
  3. Ekivenum

    Ekivenum

    Joined:
    Jan 16, 2018
    Posts:
    8
    hi,
    m_AgentIndex is an index for searching a list, so that's why there is this error.

    In Initialize i grab a gameobject and set it as a child.
     
  4. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    But in Initialize are you trying to use m_AgentIndex before the client receives it? You're making me guess because you're for some reason showing everything except the error you are getting, which is the most important part. What line in your code does the argument out of range exception occur?
     
  5. Ekivenum

    Ekivenum

    Joined:
    Jan 16, 2018
    Posts:
    8
    Hi Joe

    Thank you for your time, this is now solved.
    Here is the thing, when SetIndexAndID() line 41 is called it change playerID and agentIndex.
    Two hooked variables changed in the same methode by the server, but on non hosted connections the OnPlayerIDChange() hook is called befor m_AgentIndex is changed so i add a if(m_AgentIndex >= 0) so initialisation() is called in the right time.
    I've done the same for OnAgentIndexChange() methode:

    Code (CSharp):
    1.     private void OnAgentIndexChange(int agentIndex)
    2.     {
    3.         Debug.Log("OnAgentIndexChange");
    4.  
    5.         this.m_AgentIndex = agentIndex;
    6.         if (m_PlayerId >= 0)
    7.         {
    8.             Initialize();
    9.         }
    10.     }
    By default m_AgentIndex = -1. this index is use to seach a gameobject in a list. So myList[m_AgentIndex] gives me an error.