Почему мне нужна [Command] для NetworkServer.Spawn() , но не для NetworkServer.Destroy()?

У меня есть этот скрипт из многопользовательского шутера, который я делаю, и у меня есть вопрос об использовании атрибута [Command]

Это код:

[Command]
public void CmdShoot()
{
    //Creat the bullet
    GameObject Bullet = (GameObject)Instantiate(bulletPrefab, Barrle.transform.position, Barrle.transform.rotation);
    BulletController bc = Bullet.GetComponent<BulletController>();
    bc.SetOrigin(this.transform.name);
    NetworkServer.Spawn(Bullet);

    //Shoot the bullet
    Rigidbody rb = Bullet.GetComponent<Rigidbody>();
    rb.AddForce(cam.transform.forward * BulletForce, ForceMode.VelocityChange);
}


//Called from the bullet when it hit something
[Command]
public void CmdHit(GameObject other,GameObject _bullet)
{
    Debug.Log(other.transform.name);
    GameObject bullet = _bullet;
    if (other.GetComponent<NetworkIdentity>() != null)
    {
        //Destroy the coin if you hit it
        if (other.transform.name.Equals("Coin"))
        {
            NetworkServer.Destroy(other.gameObject);
        }

        //Apply dmg to other player if hit it
        else if (other.transform.tag.Equals("Player"))
        {
            Player playerHit = GameManager.GetPlayer(other.transform.name);
            playerHit.TakeDamage(BulletForce);
        }
    }

    //Destroy the bullet if you hit anything
    NetworkServer.Destroy(bullet.gameObject);  
}

Теперь, если я уберу атрибут [Command] из CmdShoot, удаленный игрок не сможет стрелять, потому что у него нет NetworkServer (насколько я понимаю)

Я предполагаю, что это будет то же самое для CmdHit, и удаленный игрок не сможет уничтожить пулю или монету, потому что у него нет NetworkServer.

Но... CmdHit отлично работает даже без атрибута [Command], и мне интересно, почему?


person Ron Serruya    schedule 29.07.2017    source источник


Ответы (1)


Если вы ознакомитесь с документацией Unity об удаленных действиях, это должно вам помочь. Когда вы добавляете атрибут [Command] к методу, вы помечаете этот метод как код, который будет выполняться на сервере после того, как клиент его вызовет.

В вашем случае это означает, что как только на клиенте происходит ввод, который приводит к выстрелу (например, нажатие пробела), вы сами вызываете CmdShoot(), который затем будет выполняться на сервере. Это событие нужно отправить на сервер, иначе у удаленного игрока никогда не будет этой пули. Однако CmdHit — это локальное действие, которое не обязательно выполнять на сервере — как вы написали в своем собственном комментарии к коду, CmdHit будет вызываться из пули, как только она во что-то попадет. Учитывая, что пуля существует на обоих клиентах, она попадет во что-то на обоих клиентах, так что информацию не нужно будет отправлять по сети.

person Peter Tutervai    schedule 31.07.2017
comment
Спасибо, однако мне было интересно, как я могу вызвать «NetworkServer» из функции, которая выполняется на клиенте, а не на сервере? (Если я удалю атрибут команды) - person Ron Serruya; 01.08.2017
comment
@RonSerruya, вызывающий NetworkServer, отличается в этом смысле, так как даже если код, вызывающий NetworkServer.Destroy, например, будет выполняться только на клиенте, результат этого вызова (уничтожение игрового объекта) произойдет на сервере. Я еще недостаточно поработал с сетевой частью, поэтому я в основном делаю здесь предположения, но я думаю, что ваш текущий код означает, что сервер будет несколько раз проинструктирован уничтожить игровой объект пули, каждым клиентом. - person Peter Tutervai; 01.08.2017