connectionToClient of unit return always null in RTSPlayer

Hello guys.
I faced same problem with this issue. I cannot find good answer.
connectionToClient of ServerHandleUnitSpawned always return null so unit color does not change on minimap.

Below is my RTSPlayer code.

using System;
using System.Collections;
using System.Collections.Generic;
using Mirror;
using UnityEngine;

public class RTSPlayer : NetworkBehaviour
{
    [SerializeField] private LayerMask buildingBlockLayer;
    [SerializeField] private float buildingLimit = 5f;
    [SerializeField] private Building[] buildings = new Building[0];
    [SerializeField] private Color teamColor;
    
    [SyncVar(hook = nameof(ClientHandleResourcesUpdated))]
    private int resources = 500;
    
    private List<Unit> unitList = new List<Unit>();
    private List<Building> buildingList = new List<Building>();

    public event Action<int> ClientOnResourcesUpdated;
    
    
    public List<Unit> GetMyUnits()
    {
        return unitList;
    }

    public List<Building> GetMyBuilding()
    {
        return buildingList;
    }

    public int GetResources()
    {
        return resources;
    }

    public Color GetColor()
    {
        return teamColor;
    }

    
    
    public bool CanPlaceBuilding(BoxCollider buildingCollider, Vector3 position)
    {
        if (Physics.CheckBox(
                position + buildingCollider.center,
                buildingCollider.size / 2,
                Quaternion.identity,
                buildingBlockLayer))
        {
            return false;
        }

        foreach (var building in buildingList)
        {
            if ((position - building.transform.position).sqrMagnitude
                <= buildingLimit * buildingLimit)
            {
                return true;
            }
        }

        return false;
    }
    
    #region Server

    public override void OnStartServer()
    {
        Unit.ServerOnUnitSpawned += ServerHandleUnitSpawned;
        Unit.ServerOnUnitDespawned += ServerHandleUnitDespawned;
        
        Building.ServerOnBuildingSpawned += ServerHandleBuildingSpawned;
        Building.ServerOnBuildingDespawned += ServerHandleBuildingDespawned;
    }

    public override void OnStopServer()
    {
        Unit.ServerOnUnitSpawned -= ServerHandleUnitSpawned;
        Unit.ServerOnUnitDespawned -= ServerHandleUnitDespawned;

        Building.ServerOnBuildingSpawned -= ServerHandleBuildingSpawned;
        Building.ServerOnBuildingDespawned -= ServerHandleBuildingDespawned;
    }

    private void ServerHandleUnitSpawned(Unit unit)
    {
        if (unit.connectionToClient.connectionId != connectionToClient.connectionId)
        {
            return;
        }
        
        unitList.Add(unit);
    }
    
    private void ServerHandleUnitDespawned(Unit unit)
    {
        if (unit.connectionToClient.connectionId != connectionToClient.connectionId)
        {
            return;
        }
        
        unitList.Remove(unit);
    }
    
    private void ServerHandleBuildingSpawned(Building building)
    {
        if (building.connectionToClient.connectionId != connectionToClient.connectionId)
        {
            return;
        }
        
        buildingList.Add(building);
    }
    
    private void ServerHandleBuildingDespawned(Building building)
    {
        if (building.connectionToClient.connectionId != connectionToClient.connectionId)
        {
            return;
        }
        
        buildingList.Remove(building);
    }

    [Command]
    public void CmdTryPlaceBuilding(int id, Vector3 position)
    {
        Building buildingToPlace = null;
        
        foreach (var building in buildings)
        {
            if (building.GetId() == id)
            {
                buildingToPlace = building;
                break;
            }
        }

        if (buildingToPlace == null)
        {
            return;
        }

        if (resources < buildingToPlace.GetPrice())
        {
            return;
        }

        BoxCollider buildingCollider = buildingToPlace.GetComponent<BoxCollider>();

        if (!CanPlaceBuilding(buildingCollider, position))
        {
            return;
        }

        GameObject buildingInstance =
            Instantiate(buildingToPlace.gameObject, position, buildingToPlace.transform.rotation);
        
        NetworkServer.Spawn(buildingInstance, connectionToClient);
        
        SetResources(resources - buildingToPlace.GetPrice());
    }
    
    [Server]
    public void SetResources(int resources)
    {
        this.resources = resources;
    }

    [Server]
    public void SetTeamColor(Color teamColor)
    {
        this.teamColor = teamColor;
    }
    
    #endregion

    #region Client

    public Color GetTeamColor()
    {
        return teamColor;
    }

    public override void OnStartAuthority()
    {
        if (NetworkServer.active)
        {
            return;
        }
        Unit.AuthorityOnUnitSpawned += AuthorityHandleUnitSpawned;
        Unit.AuthorityOnUnitDespawned += AuthorityHandleUnitDespawned;
        
        Building.AuthorityOnBuildingSpawned += AuthorityHandleBuildingSpawned;
        Building.AuthorityOnBuildingDespawned += AuthorityHandleBuildingDespawned;
    }

    public override void OnStopClient()
    {
        if (!isClientOnly || !hasAuthority)
        {
            return;
        }
        Unit.AuthorityOnUnitSpawned -= AuthorityHandleUnitSpawned;
        Unit.AuthorityOnUnitDespawned -= AuthorityHandleUnitDespawned;
    }
    
    private void AuthorityHandleUnitSpawned(Unit unit)
    {
        unitList.Add(unit);
    }
    
    private void AuthorityHandleUnitDespawned(Unit unit)
    {
        unitList.Remove(unit);
    }
    
    private void AuthorityHandleBuildingSpawned(Building building)
    {
        buildingList.Add(building);
    }
    
    private void AuthorityHandleBuildingDespawned(Building building)
    {
        buildingList.Remove(building);
    }

    private void ClientHandleResourcesUpdated(int oldResources, int newResources)
    {
        ClientOnResourcesUpdated?.Invoke(newResources);
    }

    #endregion
}

Below is Unit code.

using System;
using System.Collections;
using System.Collections.Generic;
using Mirror;
using UnityEngine;
using UnityEngine.Events;

public class Unit : NetworkBehaviour
{
    [SerializeField] private UnitMovement unitMovement;
    [SerializeField] private Targeter targeter;
    [SerializeField] private UnityEvent OnSelected;
    [SerializeField] private UnityEvent OnDeselected;
    [SerializeField] private Health health;
    [SerializeField] private int resourceCost = 10;
    
    public static event Action<Unit> ServerOnUnitSpawned;
    public static event Action<Unit> ServerOnUnitDespawned;

    public static event Action<Unit> AuthorityOnUnitSpawned;
    public static event Action<Unit> AuthorityOnUnitDespawned;

    public UnitMovement GetUnitMovement()
    {
        return unitMovement;
    }

    public int GetResourceCost()
    {
        return resourceCost;
    }
    public Targeter GetTargeter()
    {
        return targeter;
    }

    #region Server

    public override void OnStartServer()
    {
        ServerOnUnitSpawned?.Invoke(this);
        health.ServerOnDie += ServerHandleDie;

    }

    public override void OnStopServer()
    {
        ServerOnUnitDespawned?.Invoke(this);
        health.ServerOnDie -= ServerHandleDie;
    }
    
    [Server]
    private void ServerHandleDie()
    {
        NetworkServer.Destroy(gameObject);
    }

    #endregion
    
    #region client

    // https://edom18.hateblo.jp/entry/2017/05/30/120811
    public override void OnStartAuthority()
    {
       
        AuthorityOnUnitSpawned?.Invoke(this);
    }

    public override void OnStopClient()
    {
        if (!hasAuthority)
        {
            return;
        }
        
        AuthorityOnUnitDespawned?.Invoke(this);
    }

    [Client]
    public void Select()
    {
        if (!hasAuthority)
        {
            return;
        }
        
        OnSelected?.Invoke();
    }
    
    [Client]
    public void Deselect()
    {
        if (!hasAuthority)
        {
            return;
        }
        
        OnDeselected?.Invoke();
    }

    #endregion
}

Hi there,
I believe I had someone else with this issue recently. I think the problem turned out to be that they had an extra networkManager in the scene. Once you have the menu scene set up, there should be no networkManager in the map scene, since it is brought over from the menu scene.

Please check if this is the case. As well could you please chare any errors or warnings you are getting in the console?

Thank you for answer.
Hierarchy view is here.
Hierarchy

Console View is here.
Console

I think, first - 4th errors are known error. When I try to get RTSPlayer component, this error occurred.
When I try to create unit, 5th and 6th errors occurred.
5th message is below.

NullReferenceException: Object reference not set to an instance of an object
RTSPlayer.ServerHandleUnitSpawned (Unit unit) (at Assets/Scripts/Networking/RTSPlayer.cs:90)
Unit.OnStartServer () (at Assets/Scripts/Units/Unit.cs:41)
Mirror.NetworkIdentity.OnStartServer () (at Assets/Mirror/Runtime/NetworkIdentity.cs:673)
UnityEngine.Debug:LogException(Exception, Object)
Mirror.NetworkIdentity:OnStartServer() (at Assets/Mirror/Runtime/NetworkIdentity.cs:677)
Mirror.NetworkServer:SpawnObject(GameObject, NetworkConnection) (at Assets/Mirror/Runtime/NetworkServer.cs:1090)
Mirror.NetworkServer:Spawn(GameObject, NetworkConnection) (at Assets/Mirror/Runtime/NetworkServer.cs:1116)
UnitSpawner:ProductUnits() (at Assets/Scripts/Buildings/UnitSpawner.cs:100)
UnitSpawner:Update() (at Assets/Scripts/Buildings/UnitSpawner.cs:34)

6th message is below.

NullReferenceException: Object reference not set to an instance of an object
TeamColorSetter.OnStartServer () (at Assets/Scripts/Networking/TeamColorSetter.cs:16)
Mirror.NetworkIdentity.OnStartServer () (at Assets/Mirror/Runtime/NetworkIdentity.cs:673)
UnityEngine.Debug:LogException(Exception, Object)
Mirror.NetworkIdentity:OnStartServer() (at Assets/Mirror/Runtime/NetworkIdentity.cs:677)
Mirror.NetworkServer:SpawnObject(GameObject, NetworkConnection) (at Assets/Mirror/Runtime/NetworkServer.cs:1090)
Mirror.NetworkServer:Spawn(GameObject, NetworkConnection) (at Assets/Mirror/Runtime/NetworkServer.cs:1116)
UnitSpawner:ProductUnits() (at Assets/Scripts/Buildings/UnitSpawner.cs:100)
UnitSpawner:Update() (at Assets/Scripts/Buildings/UnitSpawner.cs:34)

There is a lot going on here. Would you like to upload your project here and I will just take a look?
https://gdev.tv/projectupload

Thank you for your kind support.
I uploaded my project to your link.
My Unity version is 2021.3.2f1, Mirror version is 66.0.9.

In the Unit Spawner in where you spawn the units you have:

GameObject unitInstance = Instantiate(
            unitPrefab.gameObject,
            unitSpawnPoint.position,
            unitSpawnPoint.rotation);

NetworkServer.Spawn(unitInstance);

Try adding the connection to client in the spawn statement:
NetworkServer.Spawn(unitInstance, connectionToClient);

That fixed it for me.

Thank you! I could solve the problem with your advice.
I really appreciate you.

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms