Havok物理引擎与Unity3D的结合

article/2025/11/4 23:04:47

背景

  在重度手游的研发过程当中,游戏中的车辆模拟,场景互动,特效展示等功能很多时候需要物理引擎的介入,以提供丰富的交互体验。目前3D手游的开发主要工具是使用Unity3D引擎,于是,如何在Unity3D的开发过程中结合入物理功能变一个需要仔细考虑的问题。

  我们考察的2种物理效果实现方案:Unity3D物理引擎和Havok物理引擎。

  Unity3d物理引擎介绍

  Unity3d在内部集成了PhysX物理引擎,为其提供了物理模拟能力。

  Physx是目前使用最为广泛的物理引擎,PhysX目前由Nvidia公司开发并维护,特点是免费且带N卡的GPU物理计算加速功能(1)。

  PhysX被很多游戏大作所采用,使用PhysX制作的游戏:


                                  

4.X版本的Unity3D集成的是2.8.3的PhysX,该版本较为老旧。在Unity5中将集成PhysX3.3,较2.8.3版本在功能和性能上有较大幅的提升,但是目前unity5并不是非常稳定。

  Havok物理引擎介绍

  Havok物理引擎是由Havok公司开发的老牌物理引擎,与PhysX不同,Havok专注于CPU端+多线程模拟方案,并且与PhysX的强大市场推广以及免费策略不同,Havok授权很严格,而且基本不提供试用版本下载(2)。

  使用Havok引擎的游戏大作在数量上与使用PhysX的不相上下,而且很多令人印象深刻:

  Unity3D物理与Havok物理的功能对比

  Unity3D集成的PhysX物理功能:

  Unity3D通过其提供的各种Component访问PhysX的物理功能,打开菜单栏中的Component->Physics便可以看到各种组件:


  其中,

  Rigidbody提供了刚体的访问接口。

  各种XXXCollider提供了3种碰撞包围体方案(Primitive,Mesh,Terrain)。

  WheelCollider组件提供了车轮模拟方案。

  XXXCloth组件提供了布料模拟方案。

  XXXJoint组件提供了关节与连接点模拟方案。

  PhysicsMaterial资源类型提供了表面物理材质描述功能。

  在Unity3D中每一种物理组件都有对应的编辑界面,且即拖即用,非常方便。



  PhysX引擎目前已经涵盖各个平台,且跨平台特性已经融入Unity3D的跨平台机制中,用户无需再关注跨平台开发。

  由于PhysX与Unity3D的深度结合以及Unity3D的闭源特性,修改PhysX的底层模拟机制基本不可能。

  Havok物理引擎功能介绍:

  Havok物理引擎以C++库的形式,通过组件式的方式,提供了丰富的物理功能。包括了:

  • Rigidbody刚体模拟。
  • 5种碰撞包围体模拟方案(Primitive,Convex,Mesh,Compount,Terrain)
  • 完整的VehicleKit车辆模拟方案。
  • HavokCloth不了模拟方案。
  • Constraint关节与连接点模拟方案。
  • HKX物理资源数据描述格式以及对应序列化与反序列化接口。
  • HavokDestruction破碎模拟方案。


  Havok并没有开发官方的Unity3D结合插件,市面上也没有第三方的结合插件可以使用,需要自行开发,有一定的开发成本。

  Havok具备称述的跨平台能力,但是由于没有结合入Unity3D的跨平台机制,在发布到多平台上需要一点额外的工作量。

  Havok在获得授权之后,用户可以修改与定制各个层级的物理功能。

  Unity和Havok主要物理功能对比



  结论:

  游戏中简单的物理效果展示可以使用生的PhysX引擎,但是如果需要扩展功能或者订制细腻的物理效果,可以考虑其它物理方案。

  Unity与Havok物理引擎的结合

  既然有结合其它物理方案的需求,那么接下来我们便讨论一下结合的方案。

  结合基本原理

  要实现Havok与Unity3D相结合,那么两个系统之间的交互通信机制便是实现的关键。Unity3D提供的二次开发平台是Mono,并没有提供NativeCode级别的接口,而Havok是完全以C++编写的Native实现。所幸,Mono为IL提供了跨平台的NativeCode交互机制。

  在Win和Linux(Android)平台上,Mono提供了以dll和so为基础的动态链接库交互C++代码形式,而在IOS平台上则是以AOT为基础的静态链接库交互形式,而这种混合编程的方法,便是让Unity3D与Havok交互的基础。
                             


  如图:结合的主要思路就是,Havok作为一个子系统,以插件的形式和Unity3D结合,并通过Mono进行交互。

  结合的具体过程:两个系统的更新流程

  由于Unity3D依然负责整个游戏的主更新流程,那么便需要将Havok的更新整合入Unity3D的流程中。一个比较合理的更新流程应该是逻辑对象先更新,然后将物理参数传入物理引擎,逻辑对象更新完成之后,物理引擎开始进行物理模拟,物理引擎返回模拟结果,Unity3D使用模拟结果进行渲染。



  要实现正确的物理效果,必须保证Havok的正确更新时序,但是多个MonoBehaviour本身更新时序就是混乱的,给结合带来了一定的难度。解决方案是,建议将整个游戏所有的逻辑对象更新收归于一个MonoBehaviour中,场景中GameObject上挂接的其余MonoBehaviour仅用于配置参数,不做任何的逻辑更新。

  结合的具体过程:两个系统关键对象的对应关系

  更新流程的结合可以保证两个系统能运转起来,但是要实现具体功能,则必须明确这两个系统之间的功能对象以及他们的对应关系。

  Unity3D的游戏世界是以Scene为单位的,而在Havok中对应的概念是HavokWorld,同一个HavokWorld中的对象才会相互碰撞。Unity3D中的游戏对象是以GameObject附带各种组件来表现,而在Havok中,刚体以HavokRigidbody表示,车辆以HavokVehicle表示,布料以HavokCloth表示,并没有一个直接对应关系,因此,需要在概念上加以封装,然后再对应。

  如果我们以CGameScene封装了UnityScene,CGameEntity封装了游戏逻辑对象,CHavokWorld封装了物理世界,CHavokEntity封装了物理功能对象,那么,以一个刚体碰撞对象为例,他们之间的对应关系应该是:



  对象关系明确之后,对象之间的更新时序也可以相应明确:



  简单描述上图中,一个刚体对象的整个功能流程是:CGameWorld中的CGameEntity在一系列逻辑更新之后,准备好了一系列的物理更新参数(可能是需要改变的额外力大小,或者是需要改变的质量大小);然后CGameEntity将这些参数设置给物理对象CHavokEntity,CHavokEntity将参数分解,交给具体的实现对象(hkpRigidbody刚体实现对象);当所有的CGameEntity都传递好参数之后,CGameWorld通知CHavokWorld,开始模拟;等模拟结束之后,所有的CGameEntity再纷纷从CHavokEntity中获取模拟的结果(由hkpRigidbody维护的位置,朝向等最终模拟结果),而这些模拟结果,最终会被设置给GameObject的Transform,拿去做下一步的逻辑处理或者直接渲染。

  结合的具体过程:物理资源制作流程的结合

  Havok拥有自己的资源描述格式:HKX。HKX可以存放从包围盒到刚体对象(hkpRigidbody实例)等很多信息,HKX拥有文本和二进制两种模式,但是任何一种模式都不被Unity3D直接支持。被结合入Unity3D的Havok物理引擎要想访问到HKX格式的资源有两种方法:

  一.将HKX文件直接放到Unity3D的StreammingAssets目录下,在Havok的C++代码层面通过不同平台的IO API去读文件。

  这样的不便之处在于需要自己维护StreammingAssets目录下的大量文件,也不能使用Unity3D的异步IO机制。



  二.利用Unity3D的ScripableObject机制,将HKX文件内容序列化到UnityAsset中,让Unity3D在IO之后以byteStream的形式传给Havok。

  好处在于,可是使用Unity3D编辑器强大的文件管理机制,以及异步IO系统。弊端在于byteStream传递过程中可能带来内存的额外开销(包括GC以及内存峰值)。



  结合的具体过程:物理场景的编辑流程结合

  Unity3D以灵活好用的编辑器著称,所以应该将场景中物理对象的编辑结合入Unity3D编辑器。提供一个可行的方案:

  以Unity3D原有的GameObject场景编辑模式为基础,在需要物理表现的GameObject上,绑定物理描述脚本,脚本中描述了物理对象的包围体资源和初始化物理信息。物理对象的初始位置可以使用GameObject的初始位置,这样当PlayScene的时候,Unity3D便可以通知Havok根据该物体的初始位置以及描述脚本中的信息去创建物理对象,进行模拟。



  如图,物理描述脚本EntityRoadBlockParam中包含了路障对象的包围体,质量,碰撞组等物理信息。这种形式的结合方案的不足之处在于,每一个Scene都必须包含Havok引擎完整的更新流程控制代码,无法做到像Unity3D原生物理引擎那样直接拖拽组件就能看到效果。

  小技巧与经验

  物理对象调试工具

  Havok提供了一个可视化的工具——Havok VisualDebugger,将物理世界的信息实时显示出来,方便调试。该工具使用Socket连接的方式与HavokRuntime实时通信,当HavokRuntime结合入Unity3D之后,依然能够正常工作,省去了我们写可视化Debugger的工作量。



  如果受限于网络环境不能使用VisualDebugger,那么手动绘制物理对象信息也是一个可选的方案,Havok提供了API可以将包围体几何信息输出(以VertexList和IndexList的形式),可以直接填入Unity3D的Mesh组件,在Gizmos或者Renderer中实时绘制,用于观察物理对象是否模拟正常。

  稳定物理模拟的帧率

  Havok物理引擎在模拟过程中需要一个稳定的更新间隔时间,如果这个间隔时而长时而短,会导致模拟不稳定,发生穿透,位置跳变等现象。解决的办法是,一旦发现间隔时间过长,则在过长的间隔时间之内,以固定的频率多模拟几次,我们称为稳定模拟模式。



  该方法可以保证物理模拟的稳定性与精确性,但是弊端是可能会进一步降低游戏的帧率。在游戏更新过程中还是应该尽量保证帧率的稳定,避免物理引擎进入稳定模拟模式。

  异步物理模拟以提升效率

  Havok默认是多线程模拟的,因此,可以对于游戏过程中仅作为表现的物理对象做异步更新,异步更新流程如图:



  异步更新的好处是可以用逻辑更新和渲染更新的时间做多线程模拟(T1 + T2时间段),降低表现物理层的模拟时间,这个方案会导致渲染层晚一帧得到物理模拟结果。但是,如果物理对象的模拟数据需要拿去做逻辑更新,那么还是需要使用同步模拟机制,否则会增大系统的复杂性。

  性能分析

  Havok结合到Unity3D之后,性能是一个需要关注的问题。我们做了一个Profile,对比Havok和Unity3D原生的Physx物理性能,用例如下:
                                              


  在场景中堆置168个Block,以一定的间隔时间给每一个Block施加一个随机力,用来扰动这些Block,使他们相互碰撞,观察模拟耗时,在Sansung Note4(3) 手机上,分析结果如下:

  PhysX_Discrete离散模式



  Havok_Discrete离散模式

  Physx_Continue连续模式



  Havok_Continue连续模式
                                            

  从分析结果上可以看出,在离散模式下,Havok和PhysX的模拟消耗差不多;但是在连续模式(4)下,PhysX的数据有点离谱,PhysX的连续模拟模式在手机上完全无法使用,而Havok则有高出离散模式一倍的开销。

  (1)大多数使用PhysX的游戏并不会使用到GPU加速功能,原因有两点:1,大多数次世代3D游戏GPU负担都非常重,并没有余力做太重度的物理模拟;2.与显卡进行数据传输也是有开销的,轻度物理模拟若算上这一部分开销,在GPU端做并没有占到很大便宜。

  (2)Havok的授权很严格,试用需要联系其商务代表。

  (3)Samsung Note4 Spec :

  PLATFORMOSAndroid OS, v4.4.4 (KitKat), v5.0.1 (Lollipop), upgradable to v5.1.1 (Lollipop)

  ChipsetQualcomm Snapdragon 805 Exynos 5433

  CPUQuad-core 2.7 GHz Krait 450 (Snapdragon 805)

  GPUAdreno 420 (Snapdragon 805)

  Mali-T760 (Exynos 5433)

  MEMORYCard slotmicroSD, up to 128 GB

  Internal32 GB, 3 GB RAM

  (4)连续模拟模式(Continuous Simulation),用于解决子弹穿纸类的问题,需要在高速小物体位置更新过程中,使用迭代计算或者射线检测等手段求的高精度碰撞检测与处理结果。


http://chatgpt.dhexx.cn/article/DCykDHWq.shtml

相关文章

unity物理引擎介绍

早期的游戏并没有强调物理引擎的应用,当时无论是哪一种游戏,都是用极为简单的计算方式做出相应的运算就算完成物理表现,如超级玛丽和音速小子等游戏。 较为常见的物理处理是在跳跃之后再次落到地上,并没有特别注重物理表现效果。…

Unity3d物理引擎

一、定义 物理引擎就是在游戏中模拟真实的物理效果,比如,场景中有一个立方体和一个球体,球体在空中,立方体在地面倾斜放置,在空中的球体开始自由下落,然后与地面上的立方体对象发生碰撞,而物理…

Unity和UE4两大游戏引擎,你该如何选择?

目录 游戏引擎 2 ——> 难易区别 编程语言 3 ——> 游戏产品 UE4制作的游戏产品 Unity制作的游戏产品 产品类型 5 ——> 资源商店 6 ——> 人才需求 平均薪资 总结 游戏引擎 Unity和UE4都是游戏引擎,所谓游戏引擎就是集成了复杂功能的游戏…

赞美之外,Unity引擎3D引擎存在什么弊病?

由于手游业界各大公司对该引擎的认可和追逐,自2013年开始,Unity大会成为了行业内最火爆的大会之一。在信息丰富的网络上,我们可以看到满屏的Unity教程和优点的介绍,但这款引擎是否存在着弊病呢?带着这个问题,我们采访…

Unity3d是目前主流的游戏开发引擎

Unity3d是目前主流的游戏开发引擎,它提供了一个整合的编辑器、跨平台发布、地形编辑、着色器,脚本,网络,物理,版本控制等特性。Unity3d可以开发桌面版、web版、手机版的游戏,是一个非常理想的三维游戏开发平…

Unity3D 游戏引擎之构建简单的游戏世界(三)

Unity3D 游戏引擎之构建简单的游戏世界 雨松MOMO原创文章如转载,请注明:转载至我的独立域名博客雨松MOMO程序研究院,原文地址:http://www.xuanyusong.com/archives/473 创建游戏地面 创建一个新的游戏工程名称命名为FirstGame,场景…

Unity3d 引擎原理详细介绍

体系结构 为了更好地理解游戏的软件架构和对象模型,它获得更好的外观仅有一名Unity3D的游戏引擎和编辑器是非常有用的,它的主要原则。 Unity3D 引擎 Unity3D的是一个屡获殊荣的工具,用于创建交互式3D应用程序在多个平台.Unity3D由游戏引擎和…

Unity3D游戏引擎最详尽基础教程

关注公众号 风色年代(itfantasycc) 200G Unity资料合集送上~ 转自:http://blog.sina.com.cn/s/blog_7c336a8301013son.html 我一直向所有想做游戏的朋友推荐Unity3D,为什么呢?首先是因为专业,Unity3D非常强…

30分钟了解所有引擎组件,132个Unity 游戏引擎组件速通!【收藏 == 学会】

前言 🎬【全网首发】 | 30分钟了解所有组件,132个Unity 游戏引擎组件速通!一、Mesh 网格1.Mesh Filter2.Mesh Renderer3.Skinned Mesh Renderer4.Text Mesh5.TextMeshPro-Text 二、Effects 特效组件1.Particle System2.Visual Effect3.Trail …

Unity 3D 物理引擎简介 || Unity 3D 物理材质|| Unity 3D 力(AddForce)

Unity 3D 物理引擎简介 早期的游戏并没有强调物理引擎的应用,当时无论是哪一种游戏,都是用极为简单的计算方式做出相应的运算就算完成物理表现,如超级玛丽和音速小子等游戏。 较为常见的物理处理是在跳跃之后再次落到地上,并没有…

Unity游戏引擎介绍及相关学习资源

Unity(游戏引擎)一般指Unity3D 官网: https://unity.com/ 手册:https://docs.unity3d.com/Manual/ Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的…

垃圾收集器及算法

一、垃圾收集算法 1.分代收集理论 当前虚拟机的垃圾收集都采用分代收集算法,只是根据对象存货周期的不同将内存分为几块。一般java堆分为新生代和老年代,可以根据各个年代的特点选择合适的垃圾收集算法。比如在新生代中,每次收集都会有大量的…

垃圾收集器-CMS

CMS垃圾收集器 文章目录 CMS垃圾收集器前言一、CMS是什么?二、CMS收集的步骤1.初始标记2.并发标记3.重新标记4.并发收集 三、核心参数四、总结 前言 相信大家都或多或少的了解过hotspot虚拟机的垃圾收集器,无论是初代的serialGc(单线程的垃圾收集器)&am…

Java经典垃圾收集器

经典垃圾收集器 1.Serial收集器2.ParNew收集器3.Parallel Scavenge收集器4.Serial Old收集器5.Parallel Old收集器6.CMS收集器7.Garbage First收集器 1.Serial收集器 Serial收集器是最基础,历史最久远的收集器,是一款新生代收集器,新生代收集…

GC 垃圾收集器

GC 垃圾回收算法 和 垃圾收集器之间的关系是什么呢 ? GC算法 (复制 / 标清 / 标整 ) 是内存回收的一种思想 , 垃圾收集器就是 GC算法 的落地实现我们知道没有最完美的 GC算法 , 因此目前为止也没有完美的垃圾收集器 , 只是针对不同的情况选择最适合的收集器来进行分代收集 主要…

7种垃圾收集器

如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。 Java虚拟机规范中对垃圾收集器应该如何实现并没有任何规定,因此不同的厂商、版本的虚拟机所提供的垃圾收集器都可能会有很大差别,并且一般都会提供参数供用户根据…

垃圾收集器简介

HotSpot JVM收集器 上面有7中收集器,分为两块,上面为新生代收集器,下面是老年代收集器。如果两个收集器之间存在连线,就说明它们可以搭配使用。 Serial(串行GC)收集器 Serial收集器是一个新生代收集器,单线程执行&…

【JVM】7种经典的垃圾收集器

文章目录 1. 垃圾收集器概述2. Serial 收集器3. ParNew 收集器4. Paraller Scavenge 收集器5. Serial Old收集器6. Parller Old收集器7. CMS 收集器8. Garbage First 收集器 本文参考:深入理解Java虚拟机:JVM高级特性与最佳实践(第3版&#x…

JVM垃圾收集器

一.概述 GC需要完成的三件事:1.哪些内存需要回收? 2.什么时候回收? 3.如何回收 Java内存运行时区域的各个部分: a. 其中程序计数器、虚拟机栈、本地方法栈三个区域随线程而生,随线程而灭;栈中的栈帧随着方法的进入和退出而有条不紊地执行…

垃圾收集算法与垃圾收集器

典型的垃圾收集算法 1.Mark-Sweep(标记-清除)算法 这是最基础的垃圾回收算法,之所以说它是最基础的是因为它最容易实现,思想也是最简单的。标记-清除算法分为两个阶段:标记阶段和清除阶段。标记阶段的任务是标记出所有…