在这里我们将跳过如何开启、编译、下载的基本步骤。并且虽然Chaos是一整套的物理引擎,本文则不对其与Phx的通用功能做出特殊说明而只针对其本身的破碎系统

资源与编辑器

GeometryCollection

我们进行破碎的第一步就是将Mesh转化为Chaos可识别的GeometryCollection资源,GeometryCollection是Chaos的物理资源。

Mesh要求

生成GeometryCollection并不是所有的Mesh都符合要求,并且为了达到更高的效率,我们依旧需要Mesh制作中符合某些特定的标准才可以。

  1. 模型需要封闭(Watertight),无交叉(Non-Intersecting)。
  2. 对于凸物体来说其分割将会更加的灵活能施加更多的控制,所以对于复炸的模型我们需要将他的Mesh拆分开,分别配置其破碎,最后通过蓝图将这些东西聚集成整体。
  3. 我们的轴向选择需要符合Unreal的Gridding Ststem的要求,这样我们控制Width和Height的时候才能更加的高效。
  4. 要考虑的另一个概念是 材质 指定,即使模块的材质相同,也应每个材质类型应用唯一的材质ID。这样在碎裂时可生成第二个材质ID,然后即可指定适当的内部材质。 在下方视频中,几何体集由两个网格体组成,而这两个网格体共享相同纹理,但使用两个不同的材质类型。因此,石料和混凝土的内面均可使用唯一材质;如果一种材质已被使用,则可将一个材质ID指定到内面。
  5. 将多个不同的Mesh整合在一个GeometryCollection中,将会使得如果有相同材质的话会共享材质并且降低DC。
  6. 多个Mesh是可以结合成为一个GeometryCollection,虽然小的物体在空间中的拜访非常灵活,但是会造成高的DrawCall,可见的接缝,并且十字交叉的重复。大型的Mesh会导致灵活性降低,但是会隐藏接缝。

创建GeometryCollection

我们使用的所有的Chaos的破碎都需要存储在Geometry Collection的资源内。

Collision Settings,

  1. Collision Type:我们的Collision Type一共有两种,一种是Implicit-Implicit一种是Particle-Implicit。他是和Implicit Type有着密不可分的关系。使用Level Set Volumes时,应将 Collision Type设为Particle-Implicit。也可将其设为 隐式-隐式(Implicit-Implicit),但其在后台仍会检查隐式表面的碰撞粒子。
  2. Implicit type:总共有四种,盒体、球体或胶囊体和Level Set Volumes。盒体以类似于边界框的形式包裹形体,而球体和胶囊体则放置在刚体内部来适应空间。 在模拟期间,这能加快计算速度并降低内存占用率,但会降低精度。Level Set Volumes,此类体积使用体素化网格对刚体采样,并生成几何体的有向距离场。Level Set Volumes精度更高,可调整的性能,不过内存使用更高
    1. Min Level Set Resolution
    2. Max Level Set Resolution
    3. MinCluster Level Set Resolution
    4. MaxCluster Level Set Resolution
  3. Collision object Reduction percentage:如Box之类的碰撞,其类似于外包围盒的那种类型,一般来说包围盒都会比破碎物体本身要打,所以我们在模拟一开始包围盒之间就会交叉,调整整个参数将会降低。

破碎系统

我们将在这里来选择我们的破碎系统

碎裂方法有多种不同类型,结合不同技巧便能产生更为有趣的破坏效果。可尝试使用不同选项和设置来实现理想效果。

使用Shift-B 可以看到Bone Color,当你选择了一个GeometryCollection. 使用Shift-Q 和Shift-E可以看分割后的场景 使用Shift-S 和Shift-W切换Levels

破碎层级 分簇

我们可以将破碎划分层级。一组相邻的碎片将会组成一个Cluster,每个Cluster也可以组成一个新的Custer。

  1. 在CusterUI中,我们使用Flatten,可以抹平所有的层级
  2. 使用Auto,我们可以自动设置层级。
  3. 在GeometryCollection上可以设置不同的Level对应的Threshold,只有到达相应的Threshold,才会继续向下破碎。

簇组索引

设置各Actor上的 簇组索引 属性为另一种可用于控制一组几何体集分簇的工具。

GamePlay

破碎事件

对于Chaos的破碎块来说,我们有两个不同的Notify,一个是Break,一个是Collision。break只的是在物体进行破碎的时候调用,而Collision与一般的Collision一样是对于每一个破碎快发生Collision的时候调用

OnChaosBreakEvent

  1. OnChaosBreakEvent,当我们增加力场,物理开始破坏时,我们将拿到这个事件。值得注意的是,这个事件的调用次数是跟破碎的块数一致的,如果我们破碎了1000个块,如果它会发出事件的话,会调用1000次。
  2. 只有GeometryCollection会产生OnChaosBreakEvent,我们可以控制它是否发送事件,通过SetNotifyBreaks.
  3. 每个OnChaosBreakEvent拥有自己的参数。我们可以根据参数来进行debug或者其他操作
    1. UPrimitiveComponent* Component;
    2. FVector Location;
    3. FVector Velocity;
    4. FVector AngularVelocity;
    5. float Mass;

OnChaosPhysicsCollision

同样的,我们的Collision也是每块都有自己的碰撞事件,其数据结构为:

USTRUCT(BlueprintType)
struct CHAOSSOLVERENGINE_API FChaosPhysicsCollisionInfo
{
	GENERATED_BODY()
public:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Chaos")
	UPrimitiveComponent* Component;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Chaos")
	UPrimitiveComponent* OtherComponent;

	/** Location of the impact */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Chaos")
	FVector Location;
	
	/** Normal at the impact */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Chaos")
	FVector Normal;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Chaos")
	FVector AccumulatedImpulse;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Chaos")
	FVector Velocity;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Chaos")
	FVector OtherVelocity;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Chaos")
	FVector AngularVelocity;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Chaos")
	FVector OtherAngularVelocity;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Chaos")
	float Mass;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Chaos")
	float OtherMass;
};

FieldSystem

我们实现所有的破碎效果都需要使用Chaos的FieldSystem。 Field使用一个空间的区域去控制物理模拟的属性。

FieldSystemComponent

使用力场来进行物理世界的模拟操作。力场的使用非常精确的控制在某一个区域中,这使得我们可以在空间中进行非常细致的控制。

同时存在多个Field System是非常普遍的,从而达到控制更加复杂和精确场景需求的目的。

在这里球体中我们添加一个Physics Field,而我们的在下面的BOX中重设我们的物理场,使得Box中完全不受到力场影响。

添加力场

最简单的添加力场的操作为ApplyPhysicsField

	void ApplyPhysicsField(bool Enabled, EFieldPhysicsType Target, UFieldSystemMetaData* MetaData, UFieldNodeBase* Field);
  1. Enabled控制是否这个力场会真正起作用。
  2. EFieldPhysicsType是物理的类型,主要有一下类型
enum EFieldPhysicsType
{
	Field_None					,
	Field_DynamicState		,//可用于将几何体集状态更新为睡眠(Sleeping)、运动(Kinematic)、静态(Static)、动态(Dynamic)或用户定义状态。
	Field_LinearForce		   ,//可用于在几何体集中用户指定的位置和方向应用力。
	Field_ExternalClusterStrain,//用于在给定体积内应用张力,若该值大于几何体集 破坏阈值,将释放簇碎片,
	Field_Kill				   ,//此类场可用于在刚体落入指定体积内时停止模拟刚体
	Field_LinearVelocity	   ,//可用于沿起点和终点生成冲击速度。
	Field_AngularVelociy	   ,//可用于在给定半径内生成冲击速度。
	Field_AngularTorque		,//可用于将指定(或随机)扭矩量应用到刚体,以获得更有趣的模拟。
	Field_InternalClusterStrain,//	用于对场内所有刚体设置张力值。
	Field_DisableThreshold	,//可用于在超过定义阈值时禁用刚体模拟。将完全移除模拟中的已禁用刚体。移除后可利用场(非碰撞)重新激活。
	Field_SleepingThreshold	,//可用于在超过定义阈值时让刚体开始睡眠。场和碰撞可唤醒并继续模拟睡眠刚体。
	Field_PositionStatic	   ,//
	Field_PositionAnimated	,//
	Field_PositionTarget	   ,//
	Field_DynamicConstraint	,//可用于约束几何体集的部分。
	Field_CollisionGroup	   ,//用于影响指定碰撞组中的几何体集。
	Field_ActivateDisabled	,//重新激活被禁用粒子。
	//256th entry
	Field_PhysicsType_Max          
};

Sleep和KillField将会去重置物理,当它的速度低于某个阈值的时候,Sleeping中的刚体是可以重新被唤醒。Disabled是指进入到这个区域后会去掉所有的物理模拟,其是完全被去除而不能重新唤醒, 3. MetaData,待研究 4. Field,场的属性。UFieldNodeBase是所有力场的父类,其子类场的类型非常丰富,例如,CullingField,UBoxFalloff,UNoiseField等等,也可以自己进行扩展。例如我们需要一些放射状的力场,Noise的力场,还可以指定是否衰减。

局部破碎

如果我们想要实现在实时过程中,指定某个区域有力场,例如射击击中的地方破碎,我们应当动态spawn一个FieldSystemActor,在其世界位置生成一个Field。

局部不破碎

使用锚场(Anchor Fields) 可用于将几何体集部分锁定在一处,而对几何体集其余部分实施碎裂。 锚场与多数场系统节点不同,由于须在模拟前建立连接图表,因此必须在构造阶段建立锚场。 因此,其逻辑在 场系统Actor 蓝图的 构造脚本 中定义,并使用 添加场命名(Add Field Command) 节点(无法使用 应用物理场(Apply Physics Field))进行引用。模拟时,如启用 分簇,在使用 张力场 应用 张力 前,抛锚几何体集将保持静态。

Niagara

Niagara系统可以与Chaos系统做出非常友善的交互,我们可以从外部蓝图中传入Niagara系统Chaos的数据,然后就可以根据Chaos的破碎位置来进行粒子的发射,这对于产生一些粉尘和小碎块非常的有帮助。

并且我们使用Niagara 的Collision和其拖尾的Event效果,可以做出浓烟爆炸等特殊的破碎效果。

性能-GeometryCollection 缓存

要改善较大模拟时的性能,建议尝试将运行时模拟改为缓存模拟。 缓存模拟适用于发生在背景中或未涉入玩家交互的破坏。Chaos未来的版本将支持在模拟和缓存模拟之间动态切换。 需首先记录缓存模拟,才能进行播放。