主机是同一进程中的服务器和客户端。主机使用一种称为的特殊客户端,而其他客户端则为RemoteClient
。LocalClient
通过直接函数调用和消息队列与(本地)服务器进行通信,因为它是在相同的过程中。它实际上与服务器共享场景。RemoteClients
通过常规网络连接与服务器进行通信。
网络系统的目标之一是将LocalClients
和RemoteClients
的代码相同,以便开发人员大多数时候只需要考虑一种类型的客户端。
在Unity中,GameObject.Instantiate
创建新的Unity游戏对象。但是,通过网络系统,对象也必须“生成”才能在网络上处于活动状态。这只能在服务器上完成,并导致在连接的客户端上创建对象。产生物体后,生成系统使用分布式对象生命周期管理和状态同步原则。
在网络系统中,玩家对象是特殊的。有一个玩家对象与每个玩游戏的人相关联,命令被路由到该对象。一个人不能对另一个人的玩家对象调用命令 - 只能是自己的。所以有一个“我的”玩家对象的概念。当添加玩家并且通过连接进行关联时,该玩家对象成为该玩家的客户端上的“本地玩家”对象。有一个属性isLocalPlayer
设置为true,并且在客户端上的对象上调用的回调OnStartLocalPlayer()
。下图显示了两个客户及其当地玩家。
只有“你的”玩家对象将设置isLocalPlayer
标志。这可以用于过滤输入处理,处理相机附件,或做任何其他客户端的事情,只能为您的玩家完成。
除了之外,玩家对象可以拥有“本地权限”。这意味着其所有者的客户端上的玩家对象对该对象负责 - 它具有权限。这最常用于控制运动,但也可以用于其他的东西。NetworkTransform
组件了解这一点,如果设置了这一点,将从客户端发送移动。NetworkIdentity
有一个用于设置LocalPlayerAuthority
的复选框。
对于非玩家对象(如敌人),没有关联的客户端,所以权限驻留在服务器上。
NetworkBehaviour
上有一个属性“hasAuthority
”,可以用来判断对象是否具有权限。因此,非玩家对象在服务器上具有权限,并且具有localPlayerAuthority
集合的玩家对象对其所有者的客户端具有权限。
向客户端分配权限会导致在对象上的NetworkBehaviours
上调用,并且hasAuthority
属性将为true
。在其他客户端上,hasAuthority
属性仍将为false
。具有客户授权的非玩家对象可以发送命令,就像玩家可以一样。这些命令在对象的服务器实例上运行,而不是在与连接相关联的玩家上运行。
具有客户端权限的非玩家对象必须在其NetworkIdentity
中检查LocalPlayerAuthority
。
下面的示例产生一个对象,并将权限分配给生成它的玩家的客户端。
NetworkBehaviour
类中有一些属性,允许脚本随时知道网络对象的网络上下文。
• isServer
- 如果对象位于服务器(或主机)上并已生成,则为true。• isClient
- 如果对象在客户端上,并且由服务器创建,则为true。• - 如果对象是此客户端的玩家对象,则为true。• hasAuthority
- 如果对象由本地进程拥有,则为true
?