Netcode for Entities里如何对Ghost进行可见性筛选(1.2.3版本)

netcode,for,entities,ghost · 浏览次数 : 0

小编点评

本文介绍了在使用Netcode for Entities进行Ghost相关功能开发时,如何通过设置GhostRelevancy来筛选和发送Ghost数据。文章详细阐述了GhostRelevancy的结构和使用方法,并提供了一个按区域过滤Ghost的示例。 1. **GhostRelevancy结构**: - GhostRelevancy是用于筛选和发送Ghost数据的组件。 - 它有三个字段:GhostRelevancyMode(设置关联性模式)、GhostRelevancySet(一个HashMap,用于存储与客户端相关的GhostId)和DefaultRelevancyQuery(一个EntityQuery,用于根据关联性模式判断Ghost是否相关)。 2. **启用筛选的方式**: - 通过设置GhostRelevancyMode来启用或禁用筛选功能。 - 使用GhostRelevancySet来填充需要发送的Ghost数据。 - 示例中展示了如何创建一个一次性执行的ISystem来设置GhostRelevancyMode,并操作GhostRelevancySet。 3. **按区域过滤Ghost**: - 通过创建一个Singleton Entity(称为SectorOperationCommands)来处理特定区域的Ghost相关操作。 - SectorOperationCommands包含四个IBufferElementData,分别代表不同的指令。 - 示例中说明了如何添加和删除Ghost,以及如何更新GhostRelevancySet。 4. **其他关键组件**: - SectorInfoCollection:保存了所有区域的数据,如GhostId和NetworkId。 - GhostChunkSerializer.cs文件中的UpdateGhostRelevancy方法:负责在Ghost更新时更新GhostRelevancySet。 总的来说,文章通过详细的步骤和示例,展示了如何在Netcode for Entities中实现基于区域的Ghost筛选和发送功能。这种方法允许开发者根据玩家的地理位置或其他条件动态地筛选和发送Ghost数据,从而提高了游戏的可玩性和交互性。

正文

一行代码省流:SystemAPI.GetSingleton<GhostRelevancy>()

当你需要按照区域、距离或者场景对Ghost进行筛选的时候,Netcode for Entities里并没有类似FishNet那样方便的过滤方式,需要获取一个过滤专用的组件:GhostRelevancy
这个结构的内容不多,但功能很强大,但用起来很累,但概念其实挺简单的:设置Ghost和客户端的关联性。有关联就发送,或者有关联就不发送。

在1.2.3版本,它里面只有三个field:

  • GhostRelevancyMode:设置关联性的模式,默认是Disabled,既无视关联性,永远向每一个客户端发送每一个Ghost
    当设置成SetIsRelevant的时候,在后面的GhostRelevancySet里面设置的GhostId会被认为是“和客户端有关联的”,则这些Ghost会向客户端发送,未设置的则不会发送
    当设置成SetIsIrrelevant的时候,规则就会反过来。
  • GhostRelevancySet:是一个HashMap,其中Value值的那个int项是没有使用到的。也就是说是当个HashSet在用的。我不知道为啥这玩意儿没有做成NativeParallelHashSet,可能是写代码的时候Unity.Collection还没有吧。
  • DefaultRelevancyQuery:一个EntityQuery,根据前面GhostRelevancyMode设置的关联性模式,通过Query的结果判断是否有关联。不过根据Changelog,这个东西应该是1.3.0才有,然而在1.2.3就已经出现在代码里了。目前可以先不管他,鬼知道里面有没有什么BUG。

启用筛选的方式也很简单,下面是我用的方案。

首先做一个一次性执行的ISystem,设置好GhostRelevancyMode。比如设置成“有关联”模式:
SystemAPI.GetSingletonRW<GhostRelevancy>().ValueRW.GhostRelevancyMode = GhostRelevancyMode.SetIsRelevant;

接下来主要就是操作GhostRelevancySet了。方法是往里面填充大量的RelevantGhostForConnection结构。这东西就是一个NetworkId和一个GhostId。把你想让某个客户端看到的每一个Ghost都做一个RelevantGhostForConnection,一股脑全扔到GhostRelevancySet里,剩下的交给系统。

至于为什么NetCode没有选择用MultiHashMap?猛一看,每一个NetworkId对应多个GhostId,好像MultiMap是更适合的数据结构。其实是因为NetCode内部实现上是在遍历每一个Ghost所在的Chunk的时候,对着GhostRelevancySetContainsKey来判断这个Ghost要不要写到Snapshot里面去的。这种方式的话不用MultiHashMap反而是更高效的方法。具体的代码在GhostChunkSerializer.cs文件里,UpdateGhostRelevancy方法内。

因为我想做的是按区域过滤,比如玩家位于区域X的时候,那么就只将区域X和这个区域附近的一圈区域内的Ghost发送给他。而玩家会在不同的区域里晃来晃去,因此我操作GhostRelevancySet方法是做了一个Singleton Entity,称为SectorOperationCommands,上面有四个IBufferElementData,每一个都代表一个指令:

  • Ghost在区域X内生成
  • Ghost在区域X内删除
  • 玩家进入区域X
  • 玩家离开区域X
    使用的时候就只需要往上面添加命令,然后写了一个ProcessSceneRelevancyCommandsSystem来统一处理。接下来调整ProcessSceneRelevancyCommandsSystem的执行顺序,确保它在所有Ghost/玩家的处理之后,GhostSendSystem之前执行即可。而GhostSendSystem是在SimulationSystemGroup里,EndSimulationEntityCommandBufferSystem后面执行的,所以只要不把处理GhostRelevancySet的ISystem丢到PresentationSystemGroup去,一般就不会有问题。

我又做了一个Singleton Entity,称为SectorInfoCollection,里面保存了所有区域的数据,比如某个区域里有哪些GhostId,有哪些NetworkId什么的。这样当玩家新进入一个特定区域的时候,要把哪些GhostId和他关联起来就很好处理了。同样的当这个区域里生成了一个Ghost,要把它和哪些NetworkId关联起来也一目了然。当然你也可以选择直接把这堆数据就放在ISystem里。因为我还要在别处用这些数据,所以做成了一个Entity。

对了,获取GhostId的方法是对着Ghost Entity来一发GetComponent<GhostInstance>()

代码就不贴了,我不喜欢在文章里贴大段大段的代码。重要的是传递概念,而不是写一堆不好CV还得人肉编译的英文符号。

与Netcode for Entities里如何对Ghost进行可见性筛选(1.2.3版本)相似的内容:

Netcode for Entities里如何对Ghost进行可见性筛选(1.2.3版本)

一行代码省流:SystemAPI.GetSingleton() 当你需要按照区域、距离或者场景对Ghost进行筛选的时候,Netcode for Entities里并没有类似FishNet那样方便的过滤方式,需要获取一个过滤专用的组件:GhostRelevancy。 这个结构的内容不多,但功能很强大

Netcode for Entities如何添加自定义序列化,让GhostField支持任意类型?以int3为例(1.2.3版本)

一句话省流:很麻烦也很抽象,能用内置支持的类型就尽量用。 首先看文档。官方文档里一开头就列出了所有内置的支持的类型:Ghost Type Templates 其中Entity类型需要特别注意一下:在同步这个类型的时候,如果是刚刚Instantiate的Ghost(也就是GhostId尚未生效,上一篇

NetCore 开源项目

前言:工作几年了,面试的时候问一堆,实则都是增删改查。感觉做net搞上位机的比较多,然而我一直做的都是web方向。以前还会背八股文,现在工作之后只会增删改,CV了。不知道后面会不会转行,唉~ 这个既是教程也是学习,我想尝试自己去做一个开源的前后端项目,看看我现在到底能做个什么样。 这篇文章,算是个开

开源.NetCore通用工具库Xmtool使用连载 - 加密解密篇

【Github源码】 《上一篇》详细介绍了Xmtool工具库中的正则表达式类库,今天我们继续为大家介绍其中的加密解密类库。 在开发过程中我们经常会遇到需要对数据进行加密和解密的需求,例如密码的加密、接口传输数据的加密等;当前类库中只封装了Base64、AES两种加密解密方法,因为C#提供了几乎我们能

开源.NetCore通用工具库Xmtool使用连载 - 散列算法篇

【Github源码】 《上一篇》详细介绍了Xmtool工具库中的加解密类库,今天我们继续为大家介绍其中的散列算法类库。 散列算法在某些特殊场景也可以当做加密方法使用;其特点是不可逆,同一内容每次散列值绝对一致,所以也可用作对数据内容是否被篡改的校验方法;或者其他需要唯一性编码的场景;本类库提供了MD

开源.NetCore通用工具库Xmtool使用连载 - 随机值篇

【Github源码】 《上一篇》 详细介绍了Xmtool工具库中的散列算法类库,今天我们继续为大家介绍其中的随机值类库。 基于系统提供的Random获取随机值方法已经足够简单和易用,本类库只对日常开发过程中最常用到的生成随机验证码方法进行了封装,后续发现其他有价值的常用随机值需求,会陆续添加到类库中

开源.NetCore通用工具库Xmtool使用连载 - 发送邮件篇

#### [【Github源码】](https://github.com/softwaiter/Xmtool) [《上一篇》](https://www.cnblogs.com/bcbr/p/17393628.html) 介绍了Xmtool工具库中的随机值类库,今天我们继续为大家介绍其中的邮件发送类库

开源.NetCore通用工具库Xmtool使用连载 - 发送短信篇

### [【Github源码】](https://github.com/softwaiter/Xmtool) [《上一篇》](https://www.cnblogs.com/bcbr/p/17421734.html) 介绍了Xmtool工具库中的发送邮件类库,今天我们继续为大家介绍其中的发送短信类库

开源.NetCore通用工具库Xmtool使用连载 - XML操作篇

### [【Github源码】](https://github.com/softwaiter/Xmtool) [《上一篇》](https://www.cnblogs.com/bcbr/p/17447376.html) 介绍了Xmtool工具库中的发送短信类库,今天我们继续为大家介绍其中的XML操作类

开源.NetCore通用工具库Xmtool使用连载 - HTTP请求篇

### [【Github源码】](https://github.com/softwaiter/Xmtool) [《上一篇》](https://www.cnblogs.com/bcbr/p/17608881.html) 介绍了Xmtool工具库中的XML操作类库,今天我们继续为大家介绍其中的HTTP请