英文原文:
https://mirror-networking.gitbook.io/docs/interest-management/custom
自定义兴趣管理
Mirror 允许您实施自定义兴趣管理解决方案。例如:
- 基于 Raycast,因此 DotA 玩家看不到墙后或灌木丛中的其他玩家
- Counter-Strike 类游戏的预测性光线投射。 穿墙外挂显示玩家在墙后。您可以创建一个自定义兴趣管理系统,仅在敌人从墙后弹出前不久将其发送给玩家。在第一人称射击游戏中,玩家移动速度很快,所以你仍然需要在他们变得可见之前发送他们几毫秒。
以上所有自定义解决方案都可以在 Mirror 中实现。要了解如何实施兴趣管理,让我们一步一步来。
脚本模板
Mirror 包括用于自定义兴趣管理的脚本模板。它完全注释了所有已经为您存根的虚拟方法覆盖。如果您之前使用过我们的旧版兴趣管理系统,那么这些应该看起来很熟悉。
- OnCheckObserver 当有人生成时调用。如果 ‘newObserver’ 可以看到 ‘identity’,则返回 true
- OnRebuildObservers 为给定的网络身份重建观察者。结果存储在 newObservers 中。
- Mirror 会在内部自动将 newObservers 放入 identity.observers 中。我们不直接这样做,因为它比添加/删除要复杂一些。Mirror管理它。没什么可担心的 :)
- RebuildAll 是一个帮助函数,用于重建每个生成的网络身份的观察者。
- 实现可能希望在每个间隔都调用它。
距离示例
距离兴趣管理是最简单、直接的实施。让我们通过它来了解如何从抽象的 InterestManagement 类继承。
public class DistanceInterestManagement : InterestManagement
{
[Tooltip("对象可见的最大范围.")]
public int visRange = 10;
[Tooltip("每隔“rebuildInterval”秒重建所有.")]
public float rebuildInterval = 1;
double lastRebuildTime;
public override bool OnCheckObserver(NetworkIdentity identity, NetworkConnection newObserver)
{
return Vector3.Distance(identity.transform.position, newObserver.identity.transform.position) <= visRange;
}
public override void OnRebuildObservers(NetworkIdentity identity, HashSet<NetworkConnection> newObservers, bool initialize)
{
Vector3 position = identity.transform.position;
// 对于每个连接
foreach (NetworkConnectionToClient conn in NetworkServer.connections.Values)
// 如果通过身份验证并加入世界
if (conn != null && conn.isAuthenticated && conn.identity != null)
// 检查距离我们的“身份”
if (Vector3.Distance(conn.identity.transform.position, position) < visRange)
// 添加到结果
newObservers.Add(conn);
}
[ServerCallback]
void Update()
{
// 每隔一段时间重建所有生成的 NetworkIdentity 的观察者
if (NetworkTime.time >= lastRebuildTime + rebuildInterval)
{
RebuildAll();
lastRebuildTime = NetworkTime.time;
}
}
}
这不是太复杂,是吗?
-
OnCheckObserver 只是比较新生成的身份和连接之间的距离。一个连接有一个主玩家,这就是我们在这里用于距离检查的东西。
- 请注意,您还可以检查连接拥有的每个对象。例如,如果 Bob 生成并且 Alice 离得不够近,Alice 的宠物可能离得足够近,因此 Alice 和 Bob 应该仍然可以看到对方,尽管有点超出正常范围。
-
OnRebuildObservers 的工作是返回可以看到我们网络身份的网络连接的 HashSet。很明显,我们只是迭代所有 NetworkServer.connections 并检查他们的主要玩家与我们的网络身份的距离。
- 请注意,我们只检查那些经过身份验证并且在世界上有玩家的人。仍在登录或选择字符的连接不应该观察到任何东西。
-
Update 的工作是不时地实际调用 RebuildAll()。如果我们不调用 RebuildAll(),那么 Mirror 将永远不会重建观察者。
主机模式可见性
在主机模式下,有人一边运行服务器一边自己玩,所以你可能会想:
- 我是服务器。服务器看到每个人。因此,我应该看到每个人。
这在技术上是正确的,但如果你有幸参加过局域网聚会,那么你会有不同的记忆:
例如,LAN 上的某个人主持 Counter-Strike 或 DotA 游戏。让我们考虑一下这个案例:
- 主机运行服务器。服务器将整个世界状态保存在内存中,而主机玩家只能看到他周围的世界。
这个想法是让主机玩家成为游戏中的常规玩家。如果您玩 DotA / Counter Strike 并且主持人总是看到其他人的位置,那么局域网聚会不会很有趣,对吗?
显然,Host可以作弊。如果你在局域网上作弊,那么你需要专业的帮助。
Mirror 有一个虚拟方法 SetHostVisibility(NetworkIdentity, bool) 可以在主机模式下启用/禁用渲染器。换句话说,世界状态仍然存在——Host 玩家只是看不到它。您可以在自定义系统中覆盖它以满足您的需求。