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

当你需要按照区域、距离或者场景对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的时候,对着GhostRelevancySet用ContainsKey来判断这个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()。

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

Netcode for Entities里如何对Ghost进行可见性筛选(1.2.3版本)的更多相关文章

  1. java里poi操作excel的工具类(兼容各版本)

    转: java里poi操作excel的工具类(兼容各版本) 下面是文件内具体内容,文件下载: import java.io.FileNotFoundException; import java.io. ...

  2. 如何在VMware8虚拟机里安装Xp GHOST系统 解决不能启动Xp系统方法

    好久没有装系统了.之前直接在硬盘中装,装个xp(c盘内).win7(d盘内).centos(虚拟机内)三系统同在一台笔记本电脑上.走了点弯路,这次记录下在虚拟机内装ghost xp. 安装步骤: 1. ...

  3. 如何在cmd窗口里快速且正确打开任意位置路径(各版本windows系统都适合)(图文详解)(博主推荐)

    问题的由来 有时候,我们很苦恼,总是先系统键 + R,然后再去手动敲.尤其对win7系统比较麻烦 解决办法 方法一:复制路径(这点对win10系统做得好,直接可以复制) ,win7系统的话可能还需要设 ...

  4. windows下修改了系统变量里java_home所引用的jdk,但是查询jdk的版本并没有发生改变

    # 原因:因为%SystemRoot%\system32 在引用这个环境变量时,会默认C:\Windows\System32下的jdk版本 # 解决方法: 把jdk的配置放在path前面就可以了

  5. 一键GHOST使用图文教程

    一.准备工作 系统安装好以后,对系统进行及时备份,以防不测,以后恢复时三五分钟即可完成,还你一个全新的完整系统. 一键GHOST V8.3 Build 060903 硬盘版免费下载 从以上地址下载软件 ...

  6. 关于ghost后4KB对齐问题

    用Ghost 11.5.1.2269(其他版本的都不行)就可以确保备份和还原后4KB对齐.

  7. 在IntelliJ IDEA里创建简单的基于Maven的SpringMVC项目

    后来发现了一种更加方便的创建方式,即第一步不选择Create from archetype,创建完毕后打开Project Structure-Modules,然后添加Web,但是注意添加的Web里面的 ...

  8. 在服务器的docker里 装anacond3深度学习环境的全流程超基础

    ​ 背景: 实验室给我分配了一个服务器 已经装好了docker 和nvidi docker . 现在我的目标是创建我自己的docker 然后在我自己的docker里装上anaconda环境. 我以前从 ...

  9. Houdini技术体系 过程化地形系统(一):Far Cry5的植被系统分析

    背景     在大世界游戏里,植被(biome)是自然环境非常重要的组成部分,虽然UE4里的也有比较不错的地形+植被系统,但相比国外AAA级游戏的效果,还是有不少的差距,简介如下: UE4的植被分为( ...

  10. 安装window 7系统----计算机经验

    上期我们已经成功制作了U盘启动并且也成功进入了PE系统了,在PE微型系统中,除了简单的装系统来恢复C盘,还有什么功能你们可以使用的呢?如果这一期我没有把其他内容讲解的话,千万别乱搞,到时我可能会讲解几 ...

随机推荐

  1. c++ lambda学习举例

    #include <iostream> #include<vector> #include<algorithm> #include<cmath> #in ...

  2. FFmpeg中的常见结构体

    代码基于FFmpeg5.0.1 目录 FFFormatContext AVFormatContext AVIOContext FFIOContext URLContext URLProtocol AV ...

  3. c# - 如何在自定义 System.Text.Json JsonConverter 中使用默认序列化?

    我正在写一个 custom System.Text.Json.JsonConverter将旧数据模型升级到新版本.我已覆盖 Read()并实现了必要的后处理.但是,我根本不需要在 Write()中做任 ...

  4. c# - 如何在圆角 WPF 窗体中创建圆角矩形?

    我正在 WPF 中创建一个应用程序,我想要圆角.收到.现在窗体是无边框的,我正在尝试创建一个圆角矩形并将其放在顶部,使其看起来像 Windows 应用程序的顶部栏. 我做不到. 这是我的代码: < ...

  5. vue3组件通信与props

    title: vue3组件通信与props date: 2024/5/31 下午9:00:57 updated: 2024/5/31 下午9:00:57 categories: 前端开发 tags: ...

  6. 鸿蒙HarmonyOS实战-Web组件(请求响应和页面调试)

    前言 请求响应是指客户端发送请求给服务器,服务器接收到请求后返回的响应.响应包含了服务器处理请求的结果,并将结果返回给客户端. 页面调试是指在开发过程中,通过调试工具分析页面的运行状况,查找问题和修复 ...

  7. NOIP模拟54

    我觉得,不改变也很好. 前言 这题太难了,场上竟然无人切题..(听说别的学校切题的人不少.. T1 选择 解题思路 范围比较小,并且每个边的度也比较小,因此考虑 树形DP+状压 . 大概就是对于每一个 ...

  8. Java异常中throw 与throws的区别

    throw 与 throws区别 在Java中,throws和throw是两个不同的关键字,它们在异常处理中起着不同的作用. throws关键字: throws用于声明一个方法可能会抛出的异常.当一个 ...

  9. 前端性能优化的利器 ——— 浅谈JavaScript中的防抖和节流

    防抖和节流函数是工作中两种常用的前端性能优化函数,今天我就来总结一下什么是防抖和节流,并详细说明一下如何在工作中应用防抖和节流函数 什么是防抖和节流? 在 JavaScript 中,防抖(deboun ...

  10. kettle从入门到精通 第二十八课 初识kettle-job

    1.前面我们一起学习了,很多转换的知识,转换为批量的开发做铺垫,今天我们一起来学习下kettle job的知识. kettle job 常用的步骤如下图,有Start.转换.作业.成功等步骤. 2.下 ...