RTS update not working for client

Hi, I have a function in Update to check the player’s myBuildings list checks the ID and adds to the units’ null references, this works for the hosts’ unit but not the clients.

  [SerializeField] private ResourceGenerator generator = null;
    private void Start()
    {
        player = NetworkClient.connection.identity.GetComponent<RTSPlayer>();
    }

LookForBuilding is in update

    private void LookForBuilding()

    {

        foreach(Building building in player.GetMyBuildings())

        {

            if (building.GetId() == genID)

            {

                ResourceGenerator reGen =  building.GetComponent<ResourceGenerator>();

                generator = reGen;

            }

        }

    }

works for the host unit but not the client,

Hi there, can you show the update() method and where LookForBuilding gets called?

So I also put a video to show what’s happening, now when I look at the worker unit for the client, the generator is null until the host building is up.
Maybe I need to do a hasAuthority somewhere for the building list but I was thinking the player connection would have taken care of that.

here is the code on the worker unit, update

private void Start()

    {

        player = NetworkClient.connection.identity.GetComponent<RTSPlayer>();

    }

    private void Update()

    {

        GatherNode gatherNode = worker.GetGather();

        timeSinceLastGather += Time.deltaTime;

        LookForBuilding();

        GatheringAction();

        if (gatherNode != null && startGathering == true)

        {

            if(!CanGatherTarget()) {return;}

            Quaternion targetRotation = Quaternion.LookRotation(

            gatherNode.transform.position - transform.position);

            transform.rotation = Quaternion.RotateTowards(

            transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);

            if (timeSinceLastGather > gatherRate)

            {  

                UpdateGatherAnimation();

                timeSinceLastGather = 0;          

            }      

        }

        if (generator != null && deliverStack == true)

        {

            if(!CanDeliverStack()){return;}

            Quaternion targetRotation = Quaternion.LookRotation(

            generator.transform.position - transform.position);

            transform.rotation = Quaternion.RotateTowards(

            transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);

            if (timeSinceLastGather > gatherRate)

            {  

                UpdateDeliverAnimation();

                timeSinceLastGather = 0;          

            } 

        }

    }
private void LookForBuilding()

    {

        foreach(Building building in player.GetMyBuildings())

        {

            if (building.GetId() == genID)

            {

                ResourceGenerator reGen =  building.GetComponent<ResourceGenerator>();

                generator = reGen;

            }

        }

    }
[SerializeField] private ResourceGenerator generator = null;

this is null until the look for building updates it, it works with the host units but the joined player unit doesn’t take in the building, one time I notice it take in the host building instead.

So you are trying to go through your list of buildings and look for any with a specific Id? Did you double check your normal building list is populating correctly? Is this script a monoBehaviour or a networkBehaviour? I would debug.log all the buildings in GetMyBuildings() as it’s iterating through to double check it’s looking at the right list.

The script is a networkBehaviour, in the hierarchy both host and joined player are taking in their correct buildings in GetMyBuildings, but when I spawn a worker for the joined player, the ResourceGenerator remains null even when the building is in the list on the joined player.

I have a debug.log in the LookForBuilding before the foreach loop, it is called when the unit is spawned.
Another debug.log after the generator = reGen, but is not called until the host place the same type of building, the worker unit is taking that building as its reference.

Show me your subscription statements for building spawning in the RTSPlayer script, this is a common source of error in this course.

public override void OnStartServer()

    {

        Unit.ServerOnUnitSpawned += ServerHandleUnitSpawned;

        Unit.ServerOnUnitDespawned += ServerHandleUnitDespawned;

        Building.ServerOnBuildingSpawned += ServerHandleBuildingSpawned;

        Building.ServerOnBuildingDespawned += ServerHandleBuildingDespawned;

        Worker.ServerOnWorkerSpawned += ServerHandleWorkerSpawned;

        Worker.ServerOnWorkerDespawned += ServerHandleWorkerDespawned;

        DontDestroyOnLoad(gameObject);

    }

    public override void OnStopServer()

    {

        Unit.ServerOnUnitSpawned -= ServerHandleUnitSpawned;

        Unit.ServerOnUnitDespawned -= ServerHandleUnitDespawned;

        Building.ServerOnBuildingSpawned -= ServerHandleBuildingSpawned;

        Building.ServerOnBuildingDespawned -= ServerHandleBuildingDespawned;

        Worker.ServerOnWorkerSpawned -= ServerHandleWorkerSpawned;

        Worker.ServerOnWorkerDespawned -= ServerHandleWorkerDespawned;

    }
//Buildings

    private void ServerHandleBuildingSpawned(Building building)

    {

        if(building.connectionToClient.connectionId != connectionToClient.connectionId){return;}

        myBuildings.Add(building);

    }

    private void ServerHandleBuildingDespawned(Building building)

    {

        if(building.connectionToClient.connectionId != connectionToClient.connectionId){return;}

        myBuildings.Remove(building);

    }

Okay so both the host and client have correctly assembled building lists that correspond to their buildings? But then the client is searching the server’s list instead of it’s own list? I’m not even sure how it would have access to that. Is the building list being synced by accident?

The building list is private with a public getter, maybe I need to do an OnSereverStart instead of a regular Start for the “player = NetworkClient.connection.identity.GetComponent();” ?

Nvm that throws errors lol

Try getting the player with:
player = connectionToClient.identity.GetComponent<RTSPlayer>();
That is how we do it in other networkBehvaiour scripts.

Yes, that did it, the unit takes in the right building, now a new problem. The unit still does not move to the node. There is a bool that is set true for the unit to start gathering but it’s not being set for the joined player unit. If I set it in the Hierarchy the unit starts gathering but it is not being set from the commandgiver.

private void TryGather(GatherNode gather)

    {

        foreach(Worker worker in unitsSelectionHandler.SelectedWorkers)

        {

            worker.CmdSetGather(gather);

            worker.GetComponent<WorkerAction>().CmdSetGatheringT();

        }

    }

The “worker.CmdSetGather(gather);” works it is setting the right gameobject, but the

worker.GetComponent<WorkerAction>().CmdSetGatheringT();

is not setting the bool true for the joined player.

At first, I had it say

worker.GetComponent<WorkerAction>().startGathering = true;

thinking it needed to be called by the client to run on the server, but neither works for the joined player just host.

Is worker action a monobehaviour?

NetworkBehaviour

Hmm, I think this has to do with your use of Cmd / [ Command] , these are for calling methods on the Server from the client. So they only run on the server.

So i changed it back to

worker.GetComponent<WorkerAction>().startGathering = true;

and added debug.logs

private void TryGather(GatherNode gather)

    {

        foreach(Worker worker in unitsSelectionHandler.SelectedWorkers)

        {

            worker.CmdSetGather(gather);

            Debug.Log("Gather");

            worker.GetComponent<WorkerAction>().startGathering = true;

            Debug.Log("True");

        }

    }

For the host both logs are called.

Joined player no logs are called, but the “GatherNode gather” is still set to the worker, and the bool is not set.

I’m thinking either TryGather is only called on the Server, or the SelectedWorkers list is only filling up on the Server and is not being populated correctly on the client.

i have the selected workers set up the same as the units

public List<Unit> SelectedUnits {get;} = new List<Unit>();

    public List<Worker> SelectedWorkers {get;} = new List<Worker>();

    private void Start()

    {

        mainCamera = Camera.main;

        player = NetworkClient.connection.identity.GetComponent<RTSPlayer>();

        Unit.AuthorityOnUnitDespawned += AuthorityHandleUnitDespawned;

        Worker.AuthorityOnWorkerDespawned += AuthorityHandleWorkerDespawned; 

        GameOverHandler.ClientOnGameOver += ClientHandleGameOver;     

    }

    private void OnDestroy()

    {

        Unit.AuthorityOnUnitDespawned -= AuthorityHandleUnitDespawned;

        Worker.AuthorityOnWorkerDespawned -= AuthorityHandleWorkerDespawned;

        GameOverHandler.ClientOnGameOver -= ClientHandleGameOver;

    }

The other movement, onselect, and ect. seems to work.
I tested the unitselection with putting a debug.log when we set target for the targeter, the log is called for the Host but not the joined player as well.
Units still attack, move, getTarget and cleartarget but the logs and bool is not being called.

Is there something i may have to change overall on the Command Giver ?

The targeter only sets the target on the Server, so that part is correct. Your client calls CmdSetTarget, which is a [Command], so the method is run on the server, to prevent cheating. The client just passes the server the gameObject it would like to target. Once the Server sets the target, the server checks for target in unitMovement and unitFiring.

So think about how to set that up similarly for your gathering. Your client should pass a gathering target to the Server. Then your server should if your unit needs to move to that target and start the movement etc.

Yes that part i have the same, the worker does get the gather object the same as the targeter, it’s not changing the bool true or false which is part if the if statement for the worker to move to the node and start gathering. I’ll try passing a bool from the command giver maybe…?

Could it be that it’s setting the bool on the client, but not passing it to the server?

Privacy & Terms