对象可见性
Unity网络支持这样一个想法,即并非服务器上的所有GameObjects
应该对游戏中的所有玩家都可见。这有时被称为“兴趣区域”,因为玩家只能看到游戏决定的与他们相关或有趣的GameObjects
。一些使用此概念的游戏功能包括战争雾,隐形和基于邻近度的可见性。当游戏世界在服务器上非常大或包含许多网络化的GameObjects
时,这一点尤其重要。减少对玩家可见的GameObjects
集减少了登录时间和持续带宽 - 因为更新只发送给玩家可见的GameObjects
。
NetworkProximityChecker
限制玩家对GameObject
可见性的最简单方法是使用内置的NetworkProximityChecker
组件。这与Unity 3D物理或2D物理系统配合使用,只允许玩家看到离他们很近的GameObjects
。要使用此组件,请将其添加到您希望限制可见性的联网GameObject
的预制中。该NetworkProximityChecker
有一些配置参数。比“可见范围”更远的GameObjects
对于玩家将不可见,并且每个玩家的可见GameObjects
集合将在每“可见更新间隔”秒被重新计算。
GameObject
必须有一个物理碰撞器才能与NetworkProximityChecker
配合使用。
远程客户端的可见性
当远程客户端上的玩家加入网络游戏时,只有该玩家可见的GameObjects
才会在该客户端上产生。所以即使玩家进入一个拥有多个网络游戏对象的大世界,进入世界的时间也可以保持合理。这适用于场景中的网络化GameObject
,但不影响资源的加载 - 已注册预制件和场景GameObjects
的资源仍将加载。
当一个玩家在世界中移动时,这组可见的GameObjects
将会改变。发生这种情况时,客户会被告知这些更改。ObjectHide
当GameObject
不再可见时,会向客户端发送一条消息。处理此消息的默认行为是销毁GameObject
。当一个GameObject
变得可见时,客户端会收到一条ObjectSpawn
消息 - 就像GameObject
是第一次创建一样。所以默认情况下,GameObject
会像其他任何产生的GameObject
一样被实例化。
在主机上的可见性
由于主机与服务器共享相同的场景,因此无法销毁对本地玩家不可见的GameObjects
。相反,有一个虚拟函数NetworkBehaviour
被调用:
public virtual void OnSetLocalVisibility(bool vis)
{
}
此功能在GameObjects
上的所有联网脚本上调用,这些脚本会更改主机上的可见性状态。这允许每个脚本定制它应该如何响应,例如通过禁用HUD元素或渲染器。默认实现NetworkProximityChecker
禁用或启用GameObject
上的所有Renderer
组件。
自定义可见性
这NetworkProximityChecker
是使用Unity Networking
的公开可视化界面实现的。使用这个接口,开发人员应该能够实现他们想要的任何一种可见性规则。每个NetworkIdentity
都会跟踪它可见的玩家组。这些被称为GameObject
的“观察者”。
NetworkIdentity
有一个功能:
// call this to rebuild the set of players observing this GameObject
public void RebuildObservers(bool initialize);
NetworkProximityChecker
在一个固定的时间间隔调用这个函数在,因此设定为每个玩家可见GameObjects
的,因为他们走动更新。
在上面NetworkBehaviour
,有一些确定可见性的虚拟功能:
// called when a new player enters the game
public override bool OnCheckObserver(NetworkConnection newObserver);
// called when RebuildObservers is invoked
public override bool OnRebuildObservers(HashSet<NetworkConnection> observers, bool initial);
OnCheckObservers
当新玩家进入游戏时,该功能在每个联网的游戏对象上的服务器上被调用。如果它返回true
,那么该玩家将被添加到GameObject
的观察者中。该NetworkProximityCheck
确实在执行这个功能的一个简单的距离检查。
该OnRebuildObservers
函数在RebuildObservers
被调用时在服务器上被调用。这个函数期望观察者集合被填充可以看到GameObject
的玩家。在NetworkServer
随后处理发送ObjectHide
和ObjectSpawn
基于旧的和新的可视性集之间的差别的消息。用于查找处于该GameObject
可见距离范围内的玩家的NetworkProximityChecker
用途Physics.OverlapSphere
。
要找出一个游戏物体是否是一名玩家,检查它的NetworkIdentity
是否具有有效的connectionToClient
。例如:
var hits = Physics.OverlapSphere(transform.position, visRange);
foreach (var hit in hits)
{
// (if a GameObject has a connectionToClient, it is a player)
var uv = hit.GetComponent<NetworkIdentity>();
if (uv != null && uv.connectionToClient != null)
{
observers.Add(uv.connectionToClient);
}
}
🔚