[动画] Unity实现《使命召唤》破碎系统!

查看:2652 |回复:5 | 2021-2-16 20:03:01

您需要 登录 才可以下载或查看,没有账号?注册

x
本帖最后由 毒游搬运小行家 于 2021-2-16 20:04 编辑

Unity实现《使命召唤》破碎系统!破碎系统在unity的实现(一)
文/游戏蛮牛

前言:场景和物件破坏在很多大型端游里都有实现,能增强游戏的表现真实性和丰富游戏的玩法,本文主要针对破碎系统的一些技术方案和在移动端的应用做一些简单的介绍。简单介绍一下基础的技术方案分类,我将破碎系统分为碎片生成和碎片表现两个方面:
640



我尝试了两种破碎系统在unity的实践方式,首先来介绍一下动态破碎的方案
  • 动态方案:平面切割算法 + 物理模拟

640

Mesh切割的流程
mesh切割流程为首先收集mesh data,然后用平面和每个mesh的三角形做切割算法,计算出新的顶点数据,其中新的顶点数据会生成新的mesh切割面(cap),所以我们需要用算法来重新构建这些cap,同时计算出新的UV,最后一步则是将cap和生成的mesh面结合生成最终的碎片mesh.下面就2个主要算法做简单的介绍:
三角形平面切割:
新的切割面的重组:主要分为下面三个步骤
将新生成的顶点转换到一个2D平面,选出参考点A,然后用每个点与A连线的向量和Y轴做点乘,用结果来进行排序.
去除重复顶点(同样或者相近的点乘结果)
计算新的Cap的bound用于UV计算
物理的模拟思路是:利用碎片的大小和切割面的法线来计算出每个碎片所受到的物理force
以上就是一次简单的平面切割和模拟碎片运动的方案,实际游戏中,如果需要多个碎片,则需要对平面切割做多次递归操作生成很多碎片.

实际测试:

1.简单mesh结构:新生成的mesh collider的bake在移动端有非常大的性能开销

2.复杂mesh结构:对于concave mesh的create cap算法有比较大的性能开销

综上所述,mesh collider的bake有很多的性能消耗,而且一般切割mesh最好是针对于convex的mesh,这样的算法复杂度会比较小而且有较小的性能消耗.
一些优化方案:
1.编辑器里做预先切割,然后在prefab里序列号碎片的运动轨迹(可以根据性能测试保存一定时间间隔的数据,然后游戏内进行插值还原表现)这样游戏内就不用开启真实的物理。
2.碎片mesh的三角形过多,可以用算法去重来减少mesh复杂度。
3.动态切割本身在低端机上可以用分帧的方式来降低性能消耗。
4.多线程物理降低bake消耗
5.SIMD优化算法性能

总结:以上简单介绍了动态破碎在unity中的实现,可以看到这种方案其实有很多局限性,主要包括:
1.物理性能不好解决,虽然可以利用预先烘焙的方式来减少消耗,但同时又失去了游戏中实时破坏的重要表现。
2.切割算法单一无法针对不同的破碎物件,比如对于花瓶或者房屋这种复杂的物理结构,平面切割算法就没那么适用,如果要做到通用性,则要引入泰森多边形或者多边形相交算法来增强表现,复杂度大并且工作流不好统一。
后面会介绍一下静态破碎的方案:即预先生成好碎片然后游戏内做表现。



破碎系统在Unity的实现(二)

本文简单介绍一下静态破碎方案在unity中的实现。静态方案即用美术工具(3DMax的插件Rayfire)制作好碎片导出到unity使用,然后在unity内处理网络同步,贴花,击飞表现等:
破碎流程框架

性能优化:
1.切好的mesh在编辑器阶段做combine mesh并记录好index数据,游戏内通过update index buffer来控制mesh的形状,来减少mesh的数量和Draw call数。

2.保留子碎片collider,避免mesh变化导致的collider重新bake的消耗,同时可以适当调整物理帧率来减少消耗。

引入houdini后的优化方案:
相对于其它的美术插件,houdini可以制作非常真实的破碎表现,可以用于CG或者游戏内的Matinee动画。
构建链接强度


定制化碎片样式:concrete, wood, glass

houdini导出破碎表现支持两种方式:
mesh + animation :
mesh + animation texture:

后者是读贴图的顶点动画,虽然性能会好一些,但是也很难满足动态的效果,网上有篇文章讲了如何结合处理这些动态效果:
该方案解决了一些破碎方式固定的问题,但也只是增加了破碎的表现种类,所以后期我又尝试了使用Houdini构建物体 + Unity模拟动画表现的方式来增加游戏效果,简单概况流程:
1.从houdini导入要破碎的mesh数据。
2.用一系列过程化操作构建破碎过程并导出数据FBX + Constrain(这里我主要写了一个简单的脚本提取了每个碎片的连接强度导出到Bridge Constrain的CSV里供后续unity还原结构使用,理论上讲,我们还可以导出如何houdini过程化制作后的数据,比如cluster等)。
3.Unity读取和还原数据结构。

关于受击力的模拟,会采用一个广度优先的方式去遍历碎片计算去掉连接的碎片,来增强模拟的真实性:
1.根据force(每种武器可以配置不同的force)来遍历计算需要断开的碎片。
2.计算失去链接的碎片
3.每个碎片给予当前位置的force.
实验效果:
开启物理后的效果


RigidBody消耗过高
关闭物理,简单模拟碎片轨迹
可以看到上面的破碎表现还是比较真实的,但是这是真实的物理情况,在手机端的性能消耗比较大,用简单的抛物线模拟碎片运动轨迹能减少物理消耗,但是表现又差强人意。这里有个优化点是用较为真实的物理模拟,利用碎片的惯性张量来模拟真实的物理旋转:

较真实的物理模拟
最后的实验效果:
真实物理模拟

物理模拟后的消耗
贴花方案:
1.表面贴花:需要修改破洞边缘的材质达到破损的效果。
每次破损收集边缘碎片 -> 计算碎片大小(center & size) -> 传入GPU ->fragment采样Decal贴图与原图blend

2.边缘贴花:边缘添加凹凸的Mesh来增加锯齿感。
计算碎片边缘edge信息->随机距离插入随机scale插片mesh->随机旋转解决Z-fighting->处理光照计算->Draw instancing减少渲染消耗.


总结:以上是houdini结合unity破碎系统的主要实现流程和一些优化方案,后期其实还有很多细节的优化点,主要有:
1.碎片分层管理
2.不同武器Damage和Force分离
3.加入Cluster的概念减少碎片数量
4.贴地模拟
5.惯性张量精确计算
6.服务器同步物件结构
7.武器类型细分等

END

评分

参与人数 1元素币 +30 活跃度 +22 展开 理由
元素界王神 + 30 + 22 【点赞】这很有大网气质!

查看全部评分

2021-2-16 20:03:01  
 赞 赞 1

使用道具 登录

5个回答,把该问题分享到群,邀请大神一起回答。
2#
心灵奇旅
回复 收起回复
2021-4-16 10:16:09   回复
 赞 赞 1

使用道具 登录

3#
厉害~~学习到了~~~~多谢楼主~~
回复 收起回复
2021-5-7 16:14:51   回复
 赞 赞 1

使用道具 登录

4#
厉害了,谢谢楼主分享!!!
回复 收起回复
2021-7-30 17:54:44   回复
 赞 赞 1

使用道具 登录

5#
回复 收起回复
2023-2-28 13:39:38   回复
 赞 赞 1

使用道具 登录

6#
回复 收起回复
2023-10-10 17:44:00   回复
 赞 赞 1

使用道具 登录

CG 游戏行业专业问题

动画技术
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表