对象可见性
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);
}
}
🔚