我们正在开发一个名为VELOCADE的车辆战斗游戏,使用Unity 6,DOTS/ECS和NetCode进行多人游戏。 这周我们添加了一个抓取钩子武器(拉近敌人或拉近表面)。 一些部分比预期更复杂,所以我想分享一下的原因,以便帮助任何人与DOTS一起工作。

为什么使用LineRenderer绘制绳子

我们曾经考虑过为绳子建造一个网格管道,但这太过于杀手了。 绳子只需要从枪口到钩子头的线,两端每帧都更新。 近端跟随移动枪,远端位于一个固定的世界点。 LineRenderer处理这个问题很干净:两个位置,一个材料,一个宽度,完成。 这与整个项目的一致性也保持一致,因为我们的迷你枪导弹和光束武器已经使用相同的方法。 对于动态端点,调用SetPosition在世界空间每帧是足够的。

ECS侧(这里有趣的地方)

DOTS烘焙掉LineRenderer。 我的第一次尝试将LineRenderer放置在本地预设中并通过GetComponentObject<LineRenderer>获取它。 它永远不起作用。 Entities Graphics只烘焙MeshRenderer/SkinnedMeshRenderer,LineRenderer不作为伴侣组件保留。 解决方案是实例化绳子从预设中在运行时并将其保留在一个池中,这正是我们的光束系统已经做的。

分析器拒绝缓存Entity。 我首先将绳子池键入为Dictionary<Entity, LineRenderer>。 项目中的Roslyn分析器(UECS001)禁止在系统中存储Entity,因为实体引用可能会过时。 我切换到一个平坦的List<LineRenderer>池,并每帧手动分发渲染器。 没有存储Entity,分析器满意。

模拟和呈现分离得到了回报。 钩子的逻辑(飞行,光线,拉近)在预测模拟组中运行。 Everything视觉(绳子,尖端,VFX,音频)生活在一个客户端仅呈现系统中。 因为模拟在火时捕获LaunchOrigin/LaunchDirection在世界空间,因此视觉也保持世界锁定。 钩子保持其空中位置,即使汽车旋转,也不会随着它一起摇摆。

一个机制,几项小但有用的DOTS教训。 TL;DR:LineRenderer是绳子的简单正确工具。 真正的工作是在ECS侧:烘焙不会保留伴侣,不能在系统中缓存Entity,尊重模拟/呈现分离保持视觉干净。

对于正在使用DOTS的人,是否使用LineRenderer绘制绳子或使用自定义网格? 我很好奇其他人如何处理它。