Search code examples
c#unity-game-engineunity3d-mirror

How to change a server variable on behalf of the client (unity mirror)


I made this shooting code via raycast

void Shoot()
{
    if (isServer)
    {
        s_Shoot();
    }
    else
    {
        c_Shoot();
    }
}

[Server]
void s_Shoot()
{
    RaycastHit hit;
    Physics.Raycast(FPScam.transform.position, FPScam.transform.forward, out hit);

    if (hit.transform.name.Contains("Player"))
    {
        Debug.Log("Hit");
        Debug.Log(hit.transform.gameObject.GetComponent<Health>().HP);
        hit.transform.gameObject.GetComponent<Health>().HP -= damage;
        Debug.Log(hit.transform.gameObject.GetComponent<Health>().HP);
    }
}

[Command]
void c_Shoot()
{
    s_Shoot();
}

Logically, on the client side, we ask the server to shoot from the camera, which is synchronized between the client and the server, and if we hit an object that has the word Player in its name, we write hit in the console, the initial health value, then in the health script that the player has in the HP variable, we remove health to the damage value and write a new health value, HP has syncvar, but only the host can remove health (although from the debug you can understand that everything except just changing the variable works) , and neither a client to a host nor a client to another client can cause damage

P.S. here is the health code (death is a function that will work if hp is less than 100, for now it just writes “death” to the console)

[SyncVar]
public int HP = 100;

void Update()
{
    if (HP <= 0)
    {
        death();
    }
}

Solution

  • I do not have a certain answer, but since it has been 20 days, I figured I would throw out a lifeline. I would guess that your problem most likely lays in the damage variable. If you change the damage variable on the client's end, the server will not see that change. Check to make sure your damage is not set to 0 when you call the function, if you have not found the issue already.

    If I am correct, you can easily fix this. One way you can fix this is by passing in a parameter into the s_Shoot function (which would look like s_Shoot(float damage)), which means that the client can tell the server how much damage to apply. The only downside to this method is that the client can tell the server to apply any amount of damage to the target, which means that hackers could one-shot any enemy with any gun in game. A more secure method would be to calculate the damage on the server's end, but the implementation of that would vary depending on what you are trying to do.