大家好。

我一直在工作于 Unity VFX Graph particles (BO VFX Physics) 的物理层。

https://i.redd.it/1ms3yombhz7h1.gif

这个想法是让 GPU 驱动的 VFX 粒子与世界互动而不需要把每个粒子都转换成一个 GameObject 或 Rigidbody。

Unity VFX Graph 已经内置了碰撞块,如 Plane、Sphere、Box、Depth Buffer 和 SDF。它们对于简单的效果很有用,但我需要更灵活和场景感知的东西:

  • 实际 Unity 的碰撞器围绕着效果;
  • 支持 MeshCollider;
  • 粒子粒子之间的交互;
  • 吸引和排斥;
  • 多个 VFX 实例在同一时间运行;
  • 池化和重启支持;
  • 不需要每个粒子一个 GameObject 或 Rigidbody。

最大的痛点是 VFX Graph 没有公开 API 来其内部的粒子缓冲区。

所以我无法直接访问 “粒子数组” 并将自己的数据附加到它上面。我必须在 VFX Graph 上建立自己的索引层:

  • 每个 VisualEffect 实例都有一个 InstanceSeed;
  • 每个 VFX 资产/组都有一个 GroupSeed;
  • GPU 粒子使用种子从哈希缓冲区中找到元数据;
  • 元数据指向共享粒子、网格和碰撞器缓冲区中的偏移量;
  • 每个 VFX 实例都有自己的槽范围在统一缓冲区中。

https://reddit.com/link/1u8yf04/video/vsq620udhz7h1/player

这也使得 vfx.startSeed 意外地重要。

在构建中,我遇到过 startSeed 在启动时为 0 的情况。对于一个普通的效果,这可能是可以接受的。但是对于我的系统,这会完全破坏 GPU 地址,因为多个实例可能会读取或写入错误的内存范围。

MeshCollider 支持是另一项工作的大部分内容。

检查粒子与每个三角形相交显然是不现实的,所以我最终建造了一个 BVH 来加速 MeshCollider 并将三角形/BVH 数据上传到 GPU 缓冲区。VFX/HLSL 一侧则通过固定大小的栈遍历 BVH。

还有很多枯燥但重要的工程工作围绕缓冲区的生命周期、重绘、虚拟缓冲区、空间网格布局、懒散网格重置和避免 GraphicsBuffers 泄漏。

所以最终,实际碰撞响应并不是最难的部分。

难点在于让 VFX Graph 像一个真正的运行时系统一样行为,具有多个实例、共享 GPU 内存、MeshCollider 加速结构和稳定的 C# 和 HLSL 之间的地址。

我不打算在这里提供下载链接,因为我想把这个帖子保持在技术层面而不是宣传层面。如果有人对这个资产感兴趣,可以通过它的名称单独找到它。