Targeting implementation only works on host

Hi,

as was already written in another post (‘Server only’ is producing different behavior to ‘Host(Server+Client)’) there is a problem with the targeting. And it does not only affect the “Server only” behavior but the targeting of the client-only player. The Target of the player is only set on the server, not synchronized back to the player.

I stumbled over that when trying to implement a target marker on the client-side. I needed the target information in the client and it was only working on the Host(Client+Server).

While this might not be needed or be fixed later in the course, due to the complexities of the Client/Server programming it is very confusing and should be at least mentioned.

I implemented the Targeter in the following way:

Targeter
public class Targeter : NetworkBehaviour
{
    [SyncVar(hook = nameof(SetTarget))]
    [SerializeField] private GameObject target = null;
    
    public Targetable GetTarget()
    {
        if(target != null &&
           target.TryGetComponent<Targetable>(out Targetable validTarget))
            return validTarget;

        return null;
    }

    #region Server

    [Command]
    public void CmdSetTarget(GameObject targetGameObject)
    {
        target = targetGameObject;
    }

    public void ClearTarget()
    {
        target = null;
    }
    
    #endregion

    #region Client

    private void SetTarget(GameObject oldTarget, GameObject newTarget)
    {
        if (oldTarget != newTarget)
        {
            target = newTarget;
        }
    }
    

    #endregion
}

The main thing was that only a GameObject can be synchronized and that I required a Targetable back from the GetTarget command.

The other thing that prevents the current state from running as Server only is the player assignment in the Update function of the UnitSelectionHandler. You can prevent the error by checking if the local client has a local player:

UnitSelectionHandler - Update()
    void Update()
    {
        
        if (player == null && NetworkClient.localPlayer != null)
        {
            player = NetworkClient.connection.identity.GetComponent<RTSPlayer>();
        }

These changes might be irrelevant to the rest of the course but are quite confusing at this time. I understand that changing such a thing in the middle of a course is not possible, but a short mention about the intentionality of the situation would be great.

1 Like

Hi there, thanks for your post!
In the scope of the course, we do not need the target information client side. We handle the targeting server side to prevent cheating.

I would say to only pass the necessary information client. In your case, if you are implementing a target marker, you probably only need to pass the transform or the position of the target. This depends on what exactly you are trying to implement.

For example, when we do projectiles in this course, the server handles everything, and then spawns the projectile on the clients with preset velocity etc. The client doesn’t need any information besides the position and speed of the projectile.

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

Privacy & Terms