UDN
Search public documentation:

PhysXDestructibleReferenceCH
English Translation
日本語訳
한국어

Interested in the Unreal Engine?
Visit the Unreal Technology site.

Looking for jobs and company info?
Check out the Epic games site.

Questions about support via UDN?
Contact the UDN Staff

UE3 主页 > 物理 >PhysX可破坏物参考指南

PhysX 可破坏物参考指南


文档概要:介绍了PhysXDestructible类。

文档变更记录: 由Bryan Galdrikian创建。

概述


PhysXDestructible是以UE3的FracturedStaticMesh (FSM)为基础的功能。首先,我们假设读者已经熟悉FSM(破裂静态网格物体)。请参照FractureTool(破裂工具)页面来熟悉那个功能。

什么时候使用PhysXDestructible而不使用FracturedStaticMesh


FracturedStaticMeshActor是在UE3关卡中生成小范围毁坏的高效方式。但是,如果您想扩大毁坏的量,不久后就会发现FracturedStaticMeshActor有一些局限性。其中一个件事情就是,生成每个的碎块(或合成物)都是通过一个AActor来表示的。如果产生了上百个碎块,那么AActor的性能消耗是相当大的。

设计PhysXDestructibleActord的目的是在需要上百个、甚至上千个刚体碎块的情况下使用它。它以两种方式来处理这个情形。首先,它把它的碎块作为SkeletalMeshes中的骨骼表示。这大大地降低了AActor的性能消耗。第二,它层次化地破裂。所以没有破裂的大碎片仍然作为一个刚体和一个SkeletalMesh(骨架网格物体)的骨骼表示。

另外,PhysXDestructibles还有一些附加的改进毁坏效果的功能。您可以分配一个“崩裂粒子系统”,它应该是个PhysXParticleSystem(请参照PhysXParticleSystemReference)。这将会呈现网格物体破裂的最精细的级别。也就是,当最小的碎片被毁坏后,它们的体积将会被PhysX流体粒子所替换。如果您使用一个网格物体数据类型,那么这将会产生逼真的碎片效果。您也可以分配一个崩裂声效和一个更加传统的粒子特效(比如烟雾或灰尘等)。

PhysXDestructibleActors可以是静态的也可以动态的。如果它们是静态的,那么有两种方法来分配那个Actor的某些部分作为“支撑物”。当一个块和支撑块之间失去邻接路径(由块片段构成)时,那个块将松动脱落下来。这个功能在FracturedStaticMeshActor中也有,但是PhysXDestructibleActor 有一个附加的功能,使得这些块和接触的actor之间创建一个支撑结构。也就是,接触PhysXDestructibleActors的孤立块将构成一个支撑结构。您可以使用这个功能,比如,使用几个PhysXDestructibleActors创建一个高的圆柱。如果您射击子弹穿过圆柱的中间,那么顶部的actors将会自动变得松散欲坠。

最后,PhysXDestructibleActor支持碰撞破坏。通过应用一个撞击破坏比例因数,当PhysXDestructibleActor受到足够大强度的碰撞(或者它以足够大的强度撞击其他对象)时将会产生破裂。

注意: 碰撞损坏目前有一个bug,该问题导致此功能不能在所有情况下都有效。我们将会尽快解决该问题。

刚开始时作为一个FracturedStaticMesh(处于未毁坏状态),直到它破裂时会利用PhysXDestructible的更加高效的静态渲染功能。

创建适当的FracturedStaticMesh(破裂静态网格物体)指南


概述: 通过使用FractureTool(破裂工具)中选择少量的碎片(大致5到20)来破裂您的静态网格物体。

更加详细地讲...FractureTool(破裂工具)可以把一个静态网格物体破裂称为适度大小的碎片。目前,这个工具至多允许150块碎片。但是,我们推荐您尽量保持这个量为较小的值(或许对于小的对象来说,可以设置为12甚至更少的数量)。原因是FracturedStaticMesh的每个破裂块都将变为一个AActor。但是,之后将不会再创建更多的AActors。这些AActors (PhysXDestructibleParts)中的每一个都是通过一个或多个SkeletalMeshes来表示的。

把您的StaticMesh破裂为 1 个碎片块也是可以的! 如果您这样做,那么当毁坏发生时,该FracturedStaticMesh将会完全地被SkeletalMesh所代替。但是,以FracturedStaticMesh开始的底层思想是使得未受到损坏的网格物体保持得尽可能的久,从而利用所提供的更加高效的渲染功能。所以,我们不推荐把网格物体破裂的数量设置的非常小(比如1)。

注意: 目前还没有考虑对其进行优化。一旦破裂了PhysXDestructible对象,所有的碎片都会变为单独的SkeletalMeshes。我们打算稍后实现静态优化。但是我们推荐您按照上面的指南进行操作,并且稍后完成的实现了这个优化的代码将会使得您的关卡呈现出的破裂效果。

如何创建PhysXDestructible


材质

尽管我们从StaticMesh(静态网格物体)开始创建,但是我们最终获得的是SkeletalMeshes(骨架网格物体)。因此在材质编辑器中为PhysXDestructible使用的任何材质选择bUsedWithSkeletalMesh选项就变得非常重要。

MaterialEditor.png

如果没有选中这个复选框,当在“在编辑器中播放”模式中运行关卡时不会产生区别,但是当在游戏中时,将不会应用该材质。

当破裂一个静态网格物体时,您必须选择将要应用到新创建的内表面的材质。同样这个材质将会应用到生成PhysXDestructible的层次化分割操作所产生的所有内表面。这里,我们已经选择了一个破裂的圆桶网格物体(如下所示)。内表面材质总是在FracturedStaticMesh的最后一个元素中。

通过在通用浏览器中双击FracturedStaticMesh 来打开它。然后在通用浏览器中选中那个内表面材质(我们选中了'PinMat')。返回到StaticMesh编辑器,打开LODInfo[0]->Elements[last index],并点击'Material(材质)'域旁边的绿色箭头,把选中的材质填充那个域。

InteriorMaterial.png

分割网格物体

在通用浏览器中右击 FracturedStaticMesh,并选择'Create New PhysX Destructible(创建新的PhysX可破坏物)'。

SelectFSM.png

当选中目标包后,命名新资源,将会弹出具有PhysXFractureOptions的对话框。这是一个"SlicingLevels(分割级别)"数组。默认情况下有一个级别,但是您可以通过点击SlicingLevels array名称旁边的绿色'+'按钮来添加更多的级别。生成的破裂碎片的数量随着每个新的级别呈几何级的增长,所以需要小心了设置该项了 ! 您可以使用'{}' 按钮来清除数组,然后再重新设置。

对于每个级别,您可以在X、Y、Z及线性和角度噪声中选择分割碎片数量。平面沿着每个坐标轴的分割数量可以是任何非负数。如果选择0,那么那个层次级别中将不会沿着该坐标轴进行分割。如果没有噪声,分割平面将有它们自己的法线,法线方向和坐标轴方向一致,并且这些法线最终会分割网格物体的边界框。AngularNoise描述了平面的法线距离分割坐标轴的距离。(将会从那个范围内选择一个随机法线。) LinearNoise描述了平面从分割坐标轴上移动的随机距离。设置这个比例,以便每个分割平面可以使得边界框的1/N作为它的"范围"(这里,N=沿着坐标轴分割的次数)。线性移动1将会把平面向右移动到下一个平面的范围附近。

默认情况下设置沿着每个坐标轴进行1次分割。这将会从每个原始碎块中最多可以生成2x2x2=8个新的碎片。这里之所以说“最多”可以生成8块,是因为如果最终分割没有和网格物体几何体相交将不会产生碎片。同样,如果分割产生了一个相对来说非常小的体积,那么也不会进行分割。

从FracturedStaticMesh碎片数量开始,下一个分割层次级别的默认分割产生的碎片(碎块)数量最多可以达到初始碎片数量的8倍。如果你添加另一个分割级别,分割数量的值还需要再次乘以那个数值。生成成百上千甚至更多的碎块是很容易的。如果碎块的数量超过1000,那么将会弹出一个警告,让您评估确认产生的碎块的数量。

关于 分割次数(X、Y和Z轴上的分割) 和 分割级别的值 的注意事项。如果想生成更多的碎片,那么最好使用另一个分割级别,而不是增加沿着每个轴的分割次数。这样做是为了使得破碎尽可能地保持层次化,从而尽可能地降低生成的刚体的数量。分割次数的一个很好的应用是把一个奇怪的网格物体分割成尺寸规则的碎块(接近于立方体)。这或许可以在第一个分割级别上完成,然后您可以在接下来的级别中仅使用1x1x1分割。一个非常极端的情况是一个非常长、非常细的物体,比如扫帚柄。您可以沿着X和Y中将平面分割次数设置为0,而沿着Z轴(假设扫帚柄在本地沿着Z轴对齐)的分割次数设置为较大(甚至可以是几十次)的值。

SlicingOptions.png

当选择完您的分割面板后,点击“OK”,就开始进行分割。这个能要花费一段时间 ! 至少要花费为每个 FracturedStaticMesh碎块生成一个 SkeletalMesh的时间。(每个SkeletalMesh 最多可以放置250碎块。如果分割产生的块数比那多,那么将会使用更多的SkeletalMeshes。) 当完成时,您将会在通用浏览器中看到很多新的PhysicsAssets和SkeletalMeshes。您可以忽略这些资源。您在关卡中创建actor所使用的是新创建的PhysXDestructible对象。

可破坏参数

在PhysXDestructible对象中可能有很多个“可破坏参数”。当您从一个PhysXDestructible初始化一个actor时,这些参数将会复制到那个actor(PhysXDestructibleActor)中,可以在actor中基于每个实例对这些参数进行修改。要想在PhysXDestructible “模板”中修改它们,请在通用浏览器中双击PhysXDestructible。将会在最顶层弹出一个具有两项的窗口: CookingScales和DestructibleParameters。我们稍后将会讨论CookingScales。目前,我们先主要集中解释DestructibleParameters(可破坏物参数)。

在通用浏览器种选中那个PhysXDestructible,并在关卡编辑窗口中右击您想创建新PhysXDestructibleActor的地方。

PhysXDestructibleProperties.png

DamageThreshold - 要想使得某个碎块掉落所需要受到的伤害量。
bAccumulateDamage - 当选中这项,应用到这个碎块上的伤害将会累积。当伤害超出伤害阈值时,碎块将会脱落。当不选中该项时,伤害将不会累积,那么只有一次单独应用的伤害量超过阈值时才能使碎块脱落。
DamageCap - 限制应用的伤害量的最大值。如果设置为0(默认情况下),将不会对应用的伤害进行限制。
DamageToRadius - 这项会把伤害转移到破坏范围内的某个距离处。如果伤害类型应用了'bFullDamage',那么在这个半径范围内的所有碎块都会应用这个伤害量。否则,伤害量将从最大伤害(在伤害原点处)开始逐渐衰减为0(在伤害半径处)。关于伤害的一些注意事项:

  • 当一个碎块受到伤害后,将从伤害量中减去DamageThreshold的值,剩余的伤害量应用到破裂层次结构中那个碎块的所有“子项碎块”上。在每个层次级别上,DamageThreshold是指使个碎块脱落所需的伤害量。当在伤害类型中应用线性衰减时,产生的效果是在靠近伤害原点处的地方网格物体破碎为更加细小的碎块;随着远离伤害远点,网格物体将会破裂为较大的碎块。
  • 伤害随着半径的实际转换变化如下所示: 伤害量除以DamageThreshold,然后将得到的结果乘以DamageToRadius,最后再乘以对象的尺寸(是指对象的边界框的宽度)。这样既缩放了伤害量也缩放了尺寸,以便使得DamageThreshold和网格物体大小都可以变化,但是伤害量的传递仍然是不变的。

ForceToDamage - 撞击力根据这个因数转换为伤害。为了使这个因数工作,那么必须在Actor的CollisionComponent中选中bNotifyRigidBodyCollision 。
CrumbleParticleSystem - 这项用于包含PhysX发射器的粒子系统。(请参照PhysXParticleSystemReference。) 您可以使用PhysX网格物体发射器来模拟崩裂。当层次结构中最低(最小)级别的碎块受到伤害量达到DamageThreshold(伤害量阈值)时,它将会被销毁。如果您已经选择了一个CrumbleParticleSystem(崩裂粒子系统),那么那个块的体积将会被一组网格物体粒子所代替。这些网格物体粒子会和几何体相碰撞,并可以模拟很多非常小的刚体。
CrumbleParticleSize - 当使用CrumbleParticleSystem[崩裂粒子系统] (参照上面)时,被销毁的块会被在这个距离上分散的粒子所填充。
FractureSound - 一个SoundCue,当一个碎块脱落(或崩塌)时将播放的它。
DepthParameters - 这是一个参数集合数组,每个碎块层次有一组参数。不能重新改变该数组的大小;该数组的大小是由碎块层次中的级别数量决定的。Set [0]为PhysXDestructibleActor提供参数。Set [1]为最顶层的碎块提供参数(每个单独的碎块代表一个FracturedStaticMesh碎块)。如果您使用1级分割,那么将会为下一个比较精细的碎块级别应用的参数集合是 set [2]。如果您使用2级分割,那么将会应用参数集合set [3],等等,以此类推。每个级别的参数是:
  • bTakeImpactDamage - 如果ForceToDamage > 0,那么撞击力将可以给这个级别应用伤害。
  • bPlaySoundEffect - 如果设置了FractureSound,那么当碎块在这个级别脱落(坍塌)时将会播放该声效。
  • bPlayParticleEffect - 碎块在这个级别中脱落毁坏,并播放FracturedStaticMesh(破裂网格物体)设置的FragmentDestroyEffect(破裂毁坏特效)。(这项是在StaticMesh(静态网格物体)编辑器中的FSM中设置的,请参照FractureTool(破裂工具) 页面。)
  • bDoNotTimeOut - 如果设置该项,只要没有超过配置变量MaxDynamicChunkCount(请参照LOD Scaling(LOD缩放),如下所示),那么该级别中的碎块就是仍然存在。如果没有设置该项,那么当时间超过配置变量DebrisLifetime(同样,请参照LOD Scaling)时,将会销毁这个碎块。

LOD缩放

PhysXDestructible有两个全局参数。它们都位于BaseEngine.ini文件及其所有衍生文件的[Engine.PhysXLODVerticalDestructible]部分。它们是:

MaxDynamicChunkCount - 该项设置了松动碎块的最大数量,对于PhysXDestructibles来说,是指松动的刚体的最大数量。这个数量是关卡中所有PhysXDestructibles的松动块数总和。这些碎块是按照先进先出的方式保存的,所以要想维持MaxDynamicChunkCount的限制就必须销毁最先脱落的碎块。
DebrisLifetime - 这项设置了碎块保持的时间。如果设置了该项,意味着没有选中bDoNotTimeOut域(请参照上面的 Destructible Parameters(毁坏参数))。

如果由于超过了碎块的最大数量或者超过了时间限制而删除了该块,那么它将使用CrumbleParticleSystem进行完全地破裂坍塌。如果没有设置CrumbleParticleSystem,那么该碎块将简单地消失。

创建一个PhysXDestructibleActor

要想创建PhysXDestructibleActor,只要简单地在通用浏览器中选择一个PhysXDestructible,并在关卡编辑器中右击您想放置该actor的位置。然后选择'Add PhysXDestructibleActor(添加PhysXDestructibleActor)...' 。(如下所示)。

CreatePhysXDestructibleActor.png

一旦把actor放置到关卡中,您可以修改实例的DestructibleParameters,缩放actor,或者使actor动态化。还有一些影响毁坏对象的“支撑物”的参数。请参照下面"支撑物"部分的内容。

打开PhysXDestructibleActor属性。

PhysXDestructibleActorProperties.png

有几个事情需要指出:

  1. DestructibleParameters是从PhysXDestructible复制而来的,并且可以会针对这个actor实例进行修改。
  2. 您可以通过把该actor的Physics(物理)修改为PHYS_RigidBody来使得PhysXDestructibleActor动态化。
  3. 如果PhysXDestructibleActor 不是动态的,那么它可能是‘支撑物’的一部分。这将会在‘支撑物’部分进行详细介绍。这里我们介绍了四个'支撑物'相关属性:
    • SupportDepth(支撑物深度) -支撑物计算是在层次结构中的这个深度上进行的。Depth = 0 (默认)意味着支撑物计算是在FracturedStaticMesh 碎片深度处完成的,也就是最大碎片数。
    • PerFrameProcessBudget - 每帧中执行支撑物计算所允许的迭代次数(逐步遍历支撑图表)。除非支撑物非常大,否则这通常不是问题。如果超过了处理预算,那么没有处理的碎块将会自动破裂脱落。
    • bSupportChunksInSupportFragment - 如果选中这项,那么仅当SupportDepth中的碎块是FracturedStaticMesh的支撑块的子项时才将其看成“支撑块”。请参照FractureTool页面。)
    • bSupportChunksTouchWorld - 如果选中这项,那么仅当碎块接触世界几何体时才把SupportDepth中的一个碎块看成“支撑块”。

创建一个崩裂的粒子系统

崩裂粒子系统使用了PhysX发射器,并且通常使用网格物体发射器来模拟崩裂效果。因为崩裂是通过“体积填充”来完成的,所以有时候会产生成百上千个流体粒子。在这种情况下,使用实例化的网格物体来渲染粒子是明智的选择。要想启用这个功能,打开您想应用粒子的材质并选中bUsedWithInstancedMeshParticles即可:

MeshHWInstancing.png

使用这种应用到网格物体粒子上的材质创建一个PhysX网格物体发射器。请参照PhysXParticleSystemReference(PhysX粒子系统参考指南)页面。

然后,打开PhysXDestructible“模板”或一个PhysXDestructibleActor实例的DestructibleParameters。在通用浏览器中选择粒子系统,并点击CrumbleParticleSystem域旁边的绿色箭头来填充它。

作为到目前为止我们所完成的效果的示例,如果我们运行那个我们创建的具有破裂圆筒的关卡,左击它来应用伤害,将会发生这样的事情:

BarrelDestroyed.png

支持

正如上面所描述的,一个静态PhysXDestructibleActor可能有一些“支撑块”。支撑块是按照如下的方式计算的: 如果一个碎块接触支撑块,那么该碎块将会受到支撑。如果一个碎块接触一个被支撑的块,那么该碎块也将会受到支撑。通过这种方式,整个actor开始相互支撑起来,但是如果支撑块已经受到足够的伤害以至于要脱落损坏时(以便碎块不再和一个被支撑的块相接处),actor的某些部分将会变为不被支撑的状态。当碎块不再受到支撑时,它们变得具有动态性。

另外,支撑结构可以在关卡中相互接触的两个或多个PhysXDestructibleActors之间相互扩展。接触PhysXDestructibleActors的每个独立块构成一个支撑架构。这样,您可以链接或“平铺”静态破坏物,以便它们看上去更像一个巨大的破坏物对象。

动态破坏不会参与支撑计算。它们不是支撑物的一部分。

作为示例,我们将创建一个破坏的墙壁碎块。EffectsDemo_Resources.Ephyra_lpwallow3产生了很好的墙壁碎块,但是它太小了。所以,这将用于展示如何进行缩放。

缩放和烘焙

继续我们的墙壁示例,我们按照上面的步骤来创建一个EffectsDemo_Resources.Ephyra_lpwallow3的PhysXDestructible。我们将使用 FractureTool来把墙壁分割成12个碎块,然后使用第二级的分割来获得更多的碎块。为了使用它,需要对其进行缩放。因此,也需要缩放碎块的碰撞模型。我们想预烘焙关卡中的这些(凸面)碰撞模型,所以我们需要指定烘焙它们所使用的缩放比例。双击PhysXDestructible,通过点击CookingScales旁边的绿色'+'按钮来添加到CookingScales数组中。然后添加您想要烘焙的缩放比例,在这种情况下,我们将选择 (10,10,10),或者进行10倍的均匀缩放。注意,如果我们不想使用没有缩放的实例,我们应该删除(1,1,1)比例的示例,以便节约关卡文件的空间。

CookingScale.png

现在,我们可以在通用浏览器中选择PhysXDestructible,并在关卡中创建一个PhysXDestructibleActor,如上所述。一旦位于关卡中,打开actor的属性表,修改DrawScale3D为(10,10,10):

ScalingADestructible.png

... 然后就可以使用缩放后的破裂物了。

支撑物示例

要想使用墙壁碎块完成这个支撑物示例,需要运行关卡,并在控制天中输入 APEXVIS SUPPORT 。如果支撑您的破裂物,那么将会描画一个支撑物表:

Support.png

这里墙壁接触着地面,所以最底下的碎块是支撑块。(因为默认情况下设置了bSupportChunksTouchWorld项。) 如果我们在编辑器中复制墙壁,并移动它以是它正好邻接到原始墙壁上面,然后支撑物图表将扩展到第二个墙壁:

Support2.png

注意,第二个墙壁不是靠自身支撑的,因为它没有接触世界几何体。(并在,在这种情况下,默认设置bSupportChunksInSupportFragment 为false。) 但是,因为它接触了被支撑的PhysXDestructibleActor,所以它也受到了支撑。这个两个墙壁构成了一个支撑物。

我们可以向较低的墙壁射击,

PartiallyDestroyedWalls.png

... 直到在较低墙壁和它上面的墙壁之间的支撑物破裂为止。

DestroyedWalls.png

已知问题


  1. 碰撞伤害并不总是有效。这或者是由于集成bug导致或者是由于PhysX SDK中的bug导致。
  2. FracturedStaticMesh在第一次受到伤害时被删除,并且会被替换为SkeletalMeshes。正在计划设计一种更加高效的可以根据需要控制破裂碎块可见性并将其替换为SkeletalMeshes的方法,从而把尽可能多的碎块表示为静态网格物体。
  3. 如果把一个网格物体分割的太精细,那么将产生一些奇怪的错误,会使得小的碎屑看上去像浮动在半空中的感觉。
  4. 对FracturedStaticMeshes和PhysXDestructibles进行的修改不会传递给关卡中的PhysXDestructibleActor实例。