RayFire for Unity 使用文档
本文档基于 坦克项目(Unity 2022+)实战集成经验整理,所有"坑点"均已在项目实际复现并解决。
一、插件概述
RayFire 是 Unity 上一款专业级物理破碎与实时粉碎特效插件,核心能力:
- 运行时无限次拆除/切片3D 对象
- 编辑器预破碎:提前生成碎片,运行时仅实例化,性能优异
- 多种破碎算法:Voronoi、Splinters、Slabs、Radial、Slices、Bricks、Voxels 等
- 支持 Skinned Mesh:可对带骨骼动画的角色/坦克进行破碎(OpenFracture 不支持)
- 完整物理模拟:碎片受重力、碰撞、爆炸力影响
- 累积伤害系统:内置 RFDamage,可实现"打几下才坍塌"的效果
二、核心组件
| 组件 | 作用 |
|---|---|
RayfireRigid | 核心组件,挂在可破碎物体上,控制物理模拟与破碎行为 |
RayfireShatter | 编辑器预破碎工具,定义碎片形状与分布 |
RayfireBomb | 爆炸物组件,挂在空物体上产生范围爆炸力 |
RayfireGun | 枪械组件,挂在空物体上发射冲击射线 |
RayfireActivator | 激活器,激活 Inactive 物体进入物理模拟 |
RayfireBlade | 切割器,对 Rigid 物体进行平面切片 |
RayfireConnectivity | 连通性组件,模拟柱状结构局部破损后上部坍塌 |
RayfireUnyielding | 固定区,标记 Connectivity 集群中不参与破碎的区域 |
RayfireMan | 全局管理器,定义材质预设、碎片池等 |
三、RayfireRigid 组件详解
3.1 Initialization(初始化方式)
| 选项 | 说明 |
|---|---|
By Method | 默认值,需代码调用Initialize()才初始化 |
At Start | Start 时自动初始化(推荐用于建筑物) |
3.2 Main(主设置)
Simulation Type(模拟类型)
| 类型 | 行为 | 适用场景 |
|---|---|---|
Dynamic | 受重力下落,可被其他物体影响 | 悬空物体、掉落碎片 |
Sleeping | 冻结直到首次碰撞,然后转为 Dynamic | 建筑物最常用,避免初始下落 |
Inactive | 冻结,需被激活才转为 Dynamic | 需要触发激活的场景 |
Kinematic | 用动画影响其他物体但自身不受影响 | 移动平台、撞击锤 |
Static | 完全不动,仅与 Dynamic 物体交互 | 地面、固定墙体 |
Object Type(对象类型)
| 类型 | 说明 |
|---|---|
Mesh | 单个物体,用自身 MeshFilter 网格模拟 |
Mesh Root | 空父物体,自动给所有带网格的直接子物体添加 Rigid |
Skinned Mesh | 破碎 SkinnedMesh(角色/坦克) |
Nested Cluster | 所有子物体作为一个整体凸体,破碎时子物体独立飞散 |
Connected Cluster | 类似 Nested,但只取第一层子物体,破碎按接触点局部脱落 |
重要坑:MeshRoot只处理直接子物体,深层嵌套的子物体会被跳过。如模型是深层结构,要么重组层级,要么手动在每个部件上添加 RayfireRigid。
Demolition Type(破碎类型)
| 类型 | 说明 | 性能 |
|---|---|---|
None | 不破碎 | - |
Runtime | 碰撞时实时生成碎片 | 最慢,低多边形适用 |
Awake Precache | Awake 时缓存碎片网格数据,碰撞时创建 GameObject | 推荐,平衡性能与内存 |
Awake Prefragment | Awake 时预破碎,所有碎片禁用等待触发 | 内存占用高,运行时最快 |
Manual Prefab Precache | 手动缓存到预制体,可保存为资产 | 预制体场景推荐 |
Manual Precache | 手动缓存,不可存为预制体 | 编辑器预生成 |
Manual Prefragment | 手动预破碎 | 编辑器预生成 |
Reference Demolition | 用预设的引用物体替换破碎 | 特殊场景 |
重要坑:使用
RayfireShatter自定义碎片形状时,Demolition Type必须设为 Awake Precache才能生效。
3.3 Demolition(破碎限制)
| 参数 | 说明 | 推荐值 |
|---|---|---|
Solidity | 物体坚固度,越低越易碎,0 = 一碰就碎 | 0.3~1 |
Depth | 破碎深度(递归次数),0 = 无限 | 1~2(街机项目) |
Time | 破碎后保护时间(秒),防止碎片刚生成就二次破碎 | 3 |
Size | 最小破碎尺寸,小于此值不再破碎 | 0.1~0.5 |
Slice by Blade | 允许被 Blade 组件切割 | 按需 |
3.4 Damage(累积伤害)— 本项目核心
| 参数 | 说明 | 推荐值 |
|---|---|---|
Enable | 必须勾选才能累积伤害 | ✅ |
Max | 伤害阈值,达到后自动 Demolish | 100(子弹 damage=30 时约打4发) |
Current | 运行时自动累积,不用手动设置 | - |
Collect | 收集伤害 | ✅ |
Multiplier | 伤害倍率 | 1 |
To Shards | 用于 ConnectedCluster | ⬜ |
重要坑:
ApplyDamage内部先检查damage.en,如果 Enable 没勾选,伤害不会累积,更不会触发破碎。
3.5 Mesh Demolition → Fragments(碎片参数)
| 参数 | 说明 | 推荐值 |
|---|---|---|
Amount | 碎片数量 | 10~30(街机)/ 50~200(PC 高配) |
Variation | 数量随机变化百分比 | 10 |
Depth Fade | 下一级深度的碎片数量倍数 | 0.5 |
Contact Bias | 接触点附近碎片更小更密集,远处更大 | 0.5~1 |
Seed | 随机种子,相同种子产生相同碎片 | 按需 |
Use Shatter | 使用 RayfireShatter 组件定义的碎片形状 | 需配合 Awake Precache |
Advanced 子区块(本项目关键配置):
| 参数 | 说明 | 本项目值 |
|---|---|---|
Clusterize | 集群化处理 | ⬜ |
Collider | 碎片碰撞体类型(Mesh / Box / Sphere / None) | Box(关键) |
Size Filter | 小于此尺寸的碎片不加碰撞体 | 0.1 |
Remove Collinear | 移除共线顶点,减少三角形 | ✅ |
重要坑:默认 Collider=Mesh 时,薄壁/平面网格的碎片顶点数 <
coplanarVertLimit,ConvexHull 失败会报错Less than four valid vertices were found。必须改为 Box。
3.6 Activation(激活方式)
仅对Inactive模拟类型有效:
| 激活方式 | 说明 |
|---|---|
By Velocity | 速度超过阈值时激活 |
By Offset | 位移超过阈值时激活 |
By Damage | 伤害值超过阈值时激活 |
By Activator | 被 RayfireActivator 组件激活 |
By Impact | 被 RayfireGun 射中时激活 |
By Connectivity | 失去与其他 Inactive 物体的连接时激活 |
重要坑:如果想让
By Velocity等激活参数生效,Demolition Type 必须设为 None,否则会失效。
四、基础使用流程
流程 1:运行时动态破碎(最简单)
适用:子弹/爆炸实时破坏建筑物
1. 场景中放置 Cube(或其他带网格物体) 2. Add Component → RayfireRigid 3. 配置: - Simulation Type = Sleeping - Object Type = Mesh - Demolition Type = Awake Precache(推荐)或 Runtime - Fragments → Amount = 15 - Fragments → Advanced → Collider = Box(关键) - Damage → Enable ✅, Max = 100 4. 运行场景,用刚体物体撞击它即可破碎流程 2:空父物体 + 多个子物体(本项目建筑物方案)
适用:复杂建筑物(由多个 Mesh 组成)
1. 层级结构: Building(空父物体,挂 RayfireRigid,ObjectType=MeshRoot) ├─ Wall_01(带 MeshFilter + BoxCollider,Is Trigger=false) ├─ Wall_02(带 MeshFilter + BoxCollider,Is Trigger=false) └─ Pillar(带 MeshFilter + BoxCollider,Is Trigger=false) 2. 父物体 RayfireRigid 配置: - Object Type = Mesh Root - Simulation Type = Sleeping - Demolition Type = Awake Precache 或 Runtime - Physics → Collider Type = Box - Damage → Enable ✅, Max = 100 - Physics → Planar Check = ⬜(关闭,否则薄壁网格不加碰撞体) 3. 每个子物体必须有 Collider(Box Collider 推荐,Mesh Collider 报错率高) 4. 点击 Editor Setup 按钮(可选) - 自动在每个直接子物体上添加子 RayfireRigid - 自动创建子物体 BoxCollider 5. 重要:MeshRoot 自身不能 Demolish,伤害必须施加在子物体的 RayfireRigid 上流程 3:使用 Bomb 爆炸(本项目爆破怪方案)
适用:爆破怪、手雷、C4 等范围爆炸
1. 可破碎物体按"流程 1"配置 RayfireRigid 2. 在爆炸点创建空 GameObject,Add Component → RayfireBomb 3. 配置 RayfireBomb: - Range = 10(爆炸半径) - Force = 500(爆炸力) 4. 代码触发爆炸: bomb.Explode(0f); // 0 表示立即爆炸 5. 避免冲击玩家:设置 Explosion Force Layer = 仅含 Fracturable 层流程 4:使用 Gun 射击
本项目不需要RayfireGun,子弹系统自行调用
ApplyDamage累积伤害。
1. 可破碎物体按"流程 1"配置 RayfireRigid 2. 在枪口位置创建空 GameObject,Add Component → RayfireGun 3. 配置 RayfireGun: - Range = 100 - Force = 300 - Radius = 0.5(冲击影响半径) 4. 代码触发射击: gun.Shoot();流程 5:编辑器预破碎(性能最优)
适用:性能敏感场景,运行时仅实例化
1. 选中物体,Add Component → RayfireShatter 2. 配置 Shatter: - Type = Voronoi(或其他碎片类型) - Amount = 20 3. 点击 Shatter 按钮,编辑器中生成碎片 4. 给碎片根物体添加 RayfireRigid,Demolition Type = None 5. 运行时通过代码触发:rigid.DemolishObject();五、碎片形状类型(RayfireShatter)
| 类型 | 说明 | 适用场景 |
|---|---|---|
Voronoi | 沃罗诺伊图,低多边形凸面碎片 | 通用默认,石头、混凝土 |
Splinters | 木片状,沿一个轴排列 | 木材、木板 |
Slabs | 石板状,沿两个轴排列 | 墙体、石板 |
Radial | 径向碎片图案 | 玻璃、圆盘 |
Custom | 自定义点云分布 | 精细控制 |
Slices | 平面分割 | 蛋糕式切片 |
Bricks | 砖块状 | 砖墙 |
Voxels | 体素化 | 方块风格 |
Tets | 四面体 | 配合胶合使用 |
六、代码 API 速查
usingRayFire;// 初始化(Initialization = By Method 时需要)RayfireRigidrigid=GetComponent<RayfireRigid>();rigid.Initialize();// 累积伤害(达到 damage.max 后自动 Demolish)rigid.ApplyDamage(damage,hitPosition,radius,hitCollider);// 触发破碎(不经过伤害累积,立即破碎)rigid.DemolishObject();// 激活 Inactive 物体rigid.Activate();// 平面切片Vector3[]slicePlanes=newVector3[]{newVector3(0,1,0),newVector3(0,1,0),// 位置, 法线};rigid.AddSlicePlane(slicePlanes);// Bomb 爆炸RayfireBombbomb=GetComponent<RayfireBomb>();bomb.Explode(0f);// 0 = 立即爆炸,>0 = 延迟秒数// Gun 射击RayfireGungun=GetComponent<RayfireGun>();gun.Shoot();6.1 ApplyDamage 重载说明
| 重载 | 适用场景 |
|---|---|
ApplyDamage(damage, pos, radius, collider) | 完整版,命中位置、影响半径、命中碰撞体(仅对 ConnectedCluster 的 shard 级别有意义) |
ApplyDamage(damage, pos, radius) | 简化版 |
ApplyDamage(damage, pos) | 最简版 |
对 MeshRoot/Mesh 类型的简单建筑物,用最简版即可(
rigid.ApplyDamage(buildingDamage, transform.position, 0f))。
七、常见坑与解决方案
7.1 基础坑(必读)
| 坑 | 原因 | 解决 |
|---|---|---|
| 物体不破碎 | Demolition Type = None | 改为 Awake Precache 或 Runtime |
| Mesh Collider 不破碎 | Unity 物理限制 | 换成 Box Collider |
| By Velocity 不生效 | Demolition Type 非 None | 设为 None |
| Shatter 自定义形状不生效 | Demolition Type 不对 | 必须设为 Awake Precache |
| 子物体错位下落 | Simulation Type = Dynamic | 改为 Sleeping 或 Inactive |
| 碎片无限递归破碎 | Depth = 0 | 设为 1 或 2 |
| SkinnedMesh 无法破碎 | OpenFracture 不支持 | 用 RayFire 的 Skinned Mesh 类型 |
| 粉色材质 | URP 不兼容 Standard Shader | 替换为 URP/Lit |
| 预制体无法保存碎片网格 | Unity Mesh 不可序列化 | 用 Manual Prefab Precache |
7.2 本项目实战踩坑点(重点)
坑 1:Mesh is not readable — Demolition type set to None
日志:
RayFire Rigid: jctBld50C_btm_lod0 Mesh is not readable. Demolition type set to None.原因:模型导入时未启用 Read/Write Enabled,RayFire 强制将 Demolition Type 设为 None。
解决:
- Project 窗口选中模型文件
- Inspector → Model → 勾选Read/Write Enabled
- 点击Apply
本项目坑点:模型常常以 LOD 形式存在(
*_lod0/*_lod1等),每个 LOD 都要单独设置。
坑 2:had planar low poly mesh — Object can’t get Mesh Collider
日志:
RayFire Rigid: jctBld50C_btm_lod0_fr_502 had planar low poly mesh. Object can't get Mesh Collider.原因:Physics → Planar Check 默认开启。检测到薄壁/平面网格(顶点数 <coplanarVertLimit)时,把 Collider Type 设为 None,导致后续 OnTriggerEnter / OnCollisionEnter 检测不到该物体。
解决(任选其一):
- 方案A(推荐):Physics → Type 设为Box
- 方案B:Physics → 取消勾选Planar Check
坑 3:ConvexHull 失败 — Less than four valid vertices
日志:
[Physics.PhysX] ConvexHullLib::cleanupVertices: Less than four valid vertices [Physics.PhysX] Failed to create Convex Mesh from source mesh "328".原因:碎片太小(顶点数 < 4),无法生成 Convex MeshCollider。这是由Mesh Demolition → Fragments → Advanced → Collider默认值 Mesh 引起的。
解决:
- Mesh Demolition → Fragments → Advanced →Collider设为Box(不是 Physics 区的 Type,是 Fragments 子区块)
- 顺便设置Size Filter= 0.1,过滤掉过小碎片
本项目坑点:Physics 区的
Type(给原物体加的碰撞体)和 Fragments 区的Collider(给碎片加的碰撞体)是两个独立配置。两个都要设为 Box 才能避免所有 ConvexHull 报错。
坑 4:MeshRoot 类型不响应 Demolish
根因:源码RFDemolitionMesh.cs:214限制:
if(scr.objectType!=ObjectType.Mesh&&scr.objectType!=ObjectType.SkinnedMesh)returntrue;// MeshRoot 直接跳过,不执行破碎场景:子弹击中子物体 →GetComponentInParent找到父级 MeshRoot → 伤害累积到阈值 → 调用Demolish()→ MeshRoot 类型直接跳过 →不破碎。
解决(任选其一):
方案A(推荐):点击父物体 RayfireRigid 的Editor Setup按钮,让 RayFire 自动在每个直接子物体上添加独立的 RayfireRigid(ObjectType=Mesh),子弹直接命中子物体的 Rigid
方案B:代码中检测到 MeshRoot 时,改为获取子物体自己的 Rigid:
if(rigid.objectType==ObjectType.MeshRoot){rigid=other.GetComponent<RayfireRigid>();// 子物体自己的}
坑 5:子弹 Trigger + 物体 Collider 触发不到
根因:Unity 物理规则——两个 Trigger 之间不会触发OnTriggerEnter,必须一方是非 Trigger。
解决:
- 子弹的 CapsuleCollider 保持
Is Trigger = true(不要改) - 建筑物子物体用BoxCollider+
Is Trigger = false(RayFire 不会自动给子物体加非Trigger的 Collider)
坑 6:Initialization = By Method 导致死循环
根因:
没有碰撞体 → 子弹检测不到建筑物 → ApplyDamage 不被调用 → Initialize() 不执行 → 碰撞体永远不创建 → 死循环解决:Initialization 必须设为At Start,让 Awake 时自动 Initialize 创建碰撞体。
坑 7:ExploderMonster 爆炸冲击玩家坦克
根因:RayfireBomb 的 mask 默认 -1(所有层),爆炸力会作用于所有带 Rigidbody 的对象,包括玩家坦克。
解决:在子物体下挂RayfireBomb时,将Explosion Force Layer设为仅含 Fracturable 层,排除 Player 层。
7.3 进阶坑
坑 8:运行时未受外力,部分模型自动破碎
原因:使用 MeshCollider 时,碎片连接处几乎必然发生碰撞,导致自我破碎。
解决:在 RayfireRigid 中勾选Ignore Near,让碎片之间不互相碰撞,只有外力才会破碎。
坑 9:一运行物体直接掉下去
原因:Simulation Type 设为 Dynamic,开局即判定为掉落。
解决:将 Simulation Type改为Inactive或Sleeping,物体冻结在空中等待激活/碰撞。
坑 10:碰撞发生了,碎片只位移不掉落
原因:没有设置激活条件,碎片只是被推开但未进入 Dynamic 状态。
解决:在 Activation 中设置激活条件,例如:
By Offset = 0.2(位移超过 0.2 米时激活掉落)- 或其他激活方式(By Velocity / By Damage / By Impact 等)
坑 11:高楼建筑底部塌了,上层浮空
原因:碎片之间没有连通性,底部碎片掉落后上层碎片没有受力源。
解决:使用RayfireConnectivity组件
- 给建筑物挂载 RayfireConnectivity(默认设置即可)
- 在 RayfireRigid 中勾选
By Connectivity激活方式 - 这样碎块连接为一个整体,底部塌陷时会带动上层
坑 12:使用 Connectivity 后整栋建筑一起被撞飞
原因:Connectivity 让所有碎块成为整体,碰撞力传递到整栋建筑,没有固定点。
解决:使用RayfireUnyielding组件设置地基
- 在建筑物底部挂载 RayfireUnyielding
- 设置 Size 定义地基范围
- 地基区域固定不动,其余部分受 Connectivity 约束
7.4 高楼建筑坍塌完整方案
1. 建筑物挂载 RayfireRigid - Simulation Type = Inactive - Demolition Type = Awake Precache - Activation → By Connectivity = 勾选 2. 建筑物挂载 RayfireConnectivity - Clusterize = 勾选 - Demolishable = 勾选(关键!让集群倒塌时进一步破碎) 3. 建筑物底部挂载 RayfireUnyielding - Size 调整为覆盖地基区域 4. 碰撞触发后效果: - 接触点局部碎裂 - 底部碎块掉落,上层保持整体 - 上层倒塌撞地时进一步破碎(Demolishable 生效) - 实现逐渐坍塌而非瞬间粉碎7.5 多个 RayfireRigid 物体重叠时互相碰撞
场景:桥梁有桥面钢筋和桥下桥墩,多个独立模型互相穿插,挂上 RayfireRigid 后立即触发碰撞。
解决:使用 Layer 隔离
- 为不同 Rayfire 物体分配不同 Layer(如
RayfireStructure/RayfirePillar) Edit → Project Settings → Physics中,取消这两个 Layer 之间的碰撞勾选- 这样重叠的 Rayfire 物体互不影响,只响应外力碰撞
八、SkinnedMesh 使用注意事项
8.1 选择正确的 ObjectType
在 RayfireRigid 中必须将ObjectType设为SkinnedMesh(枚举值为 2),组件会自动检测并处理SkinnedMeshRenderer。
8.2 破碎效果限制
- 骨骼动画影响:SkinnedMesh 的破碎效果不如普通 Mesh 理想,骨骼动画会影响破碎后碎片的行为
- 建议静止状态破碎:在模型静止时触发破碎,避免动画状态下破碎导致碎片位置异常
8.3 性能开销
- SkinnedMesh 破碎计算量较大,特别是运行时实时破碎
- 建议限制碎片数量(通过 RayfireRigid 的 Limitations 参数)
- 对于复杂模型,考虑预破碎预制体
8.4 材质与纹理
确保 SkinnedMeshRenderer 的材质和纹理设置正确,破碎后碎片会继承原始材质。
8.5 替代方案(推荐)
对于需要良好破碎效果的模型,建议:
- 在 3D 软件中拆分为多个 Mesh 部件
- 使用
MeshRoot类型获得更好的破碎效果和性能
九、与本项目集成现状
9.1 子弹命中建筑物
参考 [RTCTankBullet.cs](file:///d:/Projects/G320/UnityProject/G320/Assets/Packages/Physics%20Based%20Tank%20Controller/Scripts/RTCTankBullet.cs) 的TryFractureBuilding:
privatevoidTryFractureBuilding(Colliderother){if(other==null)return;RayfireRigidrigid=other.GetComponent<RayfireRigid>();if(rigid==null)rigid=other.GetComponentInParent<RayfireRigid>();if(rigid==null)return;rigid.ApplyDamage(buildingDamage,transform.position,0f);}本项目建筑物配置:
| 配置项 | 值 |
|---|---|
| Object Type | Mesh Root |
| Simulation Type | Sleeping |
| Demolition Type | Awake Precache / Runtime |
| Physics → Type | Box |
| Physics → Planar Check | ⬜ |
| Fragments → Advanced → Collider | Box |
| Fragments → Advanced → Size Filter | 0.1 |
| Damage → Enable | ✅ |
| Damage → Max | 100 |
| Initialization | At Start |
子弹配置:
buildingDamage= 30(打4发左右坍塌)- 子弹 CapsuleCollider
Is Trigger = true - 建筑物子物体 BoxCollider
Is Trigger = false
9.2 爆破怪自身爆炸
参考 [ExploderMonster.cs](file:///d:/Projects/G320/UnityProject/G320/Assets/Scripts/Monster/ExploderMonster.cs):
// TriggerSelfDestruction 中if(_rayfireRigid!=null)_rayfireRigid.Initialize();if(_rayfireBomb!=null){_rayfireBomb.strength=selfExplosionForce;_rayfireBomb.range=explodeRadius;_rayfireBomb.Explode(0f);}关键配置:
Explosion Force Layer= 仅 Fracturable 层(避免冲击玩家坦克)Initialization= At Start- 模型需要 Read/Write Enabled
9.3 集成检查清单
- 模型导入启用 Read/Write Enabled
- Initialization = At Start
- Physics → Type = Box
- Physics → Planar Check = ⬜
- Fragments → Advanced → Collider = Box
- Fragments → Advanced → Size Filter = 0.1
- Demolition Type = Awake Precache 或 Runtime
- Damage → Enable ✅, Max > 0
- Simulation Type = Sleeping(建筑物)/ Dynamic(爆破怪)
- 子物体有 BoxCollider 且 Is Trigger = false
- MeshRoot 父物体已点击 Editor Setup(或代码中处理 MeshRoot 跳过)
十、性能优化建议
- 优先使用预破碎:Awake Prefragment 或 Manual Prefragment,运行时零计算开销
- 限制 Depth:设为 1 或 2,避免碎片无限递归
- 设置 Size 限制:小于阈值的碎片不再破碎,减少碎片数量
- 使用 Sleeping 模式:未碰撞时不参与物理计算
- 碎片对象池:RayfireMan 组件可配置碎片池复用
- 简化碎片 Collider:小碎片用BoxCollider 代替 Mesh Collider(避免 ConvexHull 报错)
- 异步缓存:Runtime Caching 设为 By Frames,分帧生成碎片避免卡顿
- LOD 模型:每个 LOD 都要单独设置 Read/Write Enabled
十一、参考资源
- 官方文档 - Rigid Component
- CSDN - 破碎插件 RayFire 的使用
- CSDN - Rayfire Rigid 组件参数含义
- CSDN - 使用 bomb 或 gun 摧毁物体
- CSDN - Activation By Velocity 不生效问题
- CSDN - unity Rayfire 破碎插件的踩坑点
- B站 - RayFire for Unity 教程视频
- B站专栏 - RayFire 使用心得
- CSDN - Rayfire Connectivity 组件