【问题标题】:Spawning prefabs in Command在 Command 中生成预制件
【发布时间】:2021-03-31 22:38:44
【问题描述】:

我是统一制作多人游戏的新手。我正在尝试在玩家身上生成子弹预制件我的问题是我是否必须生成我的预制件,即使它是使用命令在服务器中的客户端子弹

[Command]
void InstantiateHook()
{
    bullet = Instantiate(bulletPrefab, this.transform.position, Quaternion.identity);
    NetworkServer.Spawn(bullet );
}

我可以在播放器脚本中使用普通函数生成它吗

void InstantiateHook()
{
    bullet = Instantiate(bulletPrefab, this.transform.position, Quaternion.identity);
    NetworkServer.Spawn(bullet );
}

【问题讨论】:

    标签: unity3d


    【解决方案1】:

    权威

    了解 Unity 多人游戏中的权威性很重要。作为客户端,默认情况下,您唯一有权控制的是您的本地播放器来发送命令。任何权限都必须通过服务器授予客户端。服务器是上帝,默认拥有一切权限。

    网络身份

    了解服务器和客户端的通信方式也很重要。每个(联网的)对象都有一个网络标识,用于标识网络中的一个对象。标识此对象的主编号是一个无符号整数,称为 netID。此 netID 是一个唯一标识符,在所有客户端中都是一致的。例如,如果我们有玩家 A、玩家 B 和一个 Bullet,玩家 A 的 netID 可能为 0,并且此 ID 在包括服务器在内的每个客户端中都是一致的。这样,如果我从播放器 A 调用命令来更改播放器中的变量,它就会知道我这样做是因为 netID。

    网络层次结构

    现在我们了解了基本的网络同步和权限,我们可以了解网络游戏的基本层次结构。每个联网的对象都由每个客户端和服务器共享(与前面所述相同的 netID)。例如,如果我们想生成一个子弹,我们需要服务器为一个对象分配一个 netID 并将这个子弹分发给所有客户端。现在我们有了一个具有一致 netID 的子弹游戏对象,并且完美同步,因为该对象是在服务器和客户端上实例化的。

    命令的工作原理

    当我们在播放器对象上调用命令时,请记住此播放器对象位于每个客户端和服务器上。因此,当我们调用命令时,此函数不再运行在客户端播放器对象上,而是运行在服务器播放器对象上。这很关键,因为这就是我们拥有如此高权限的原因。

    NetworkServer.Spawn

    所以在你的情况下,我们需要首先调用一个命令,这将赋予我们对服务器的权限和访问权限。在我们这样做之后,我们需要调用一个函数来实例化子弹,而 UNet/Mirror 应该通过 NetworkServer.Spawn 自动执行此操作。

    所以你的代码应该看起来像

    //Somewhere in your player script
    
    public GameObject bulletPrefab; //Assign this in the unity inspector as your bullet prefab
    
    [Command]
    private void CmdSpawnBullet() {
        GameObject myNewBullet = Instantiate(bulletPrefab); //Create a new bullet on the server
    
        //Now we have a bullet on the server, let's also spawn this on the clients to be synced
    
        NetworkServer.Spawn(myNewBullet); //A second parameter is optional, this is the network connection to assign authority to. In this case, the server would probably have authority since hacking would be rather easy if the client had authority over the bullets.
    }
    
    private void Update() {
        if (!isLocalPlayer) return; //Wouldn't want any other clients running this for your player
    
        if (Input.GetMouseButtonDown(0)) {
            CmdSpawnBullet(); //Spawn a bullet when we click our primary fire button
        }
    }
    

    此脚本将在所有客户端上生成一个子弹。这颗子弹当然不会有任何作用,但那是为了你自己的游戏欲望:)

    还有一个我忘记添加的快速注释。您不能从您没有权限的对象调用命令。例如,如果你是玩家 A,并且有一个子弹是服务器有权限的,那么你不能从这个子弹调用命令,因为你没有权限。除非您在属性中添加 requiresAuthority=false 标记。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-03
      相关资源
      最近更新 更多