跳转至

:material-physics: Week6 — 物理系统

游戏物理

基本要素

  • Body和Shape:Body包含一些基本属性,如质量、位置、速度、角速度等,Shape则是碰撞体,一个Body可以有多个Shape。

Shape

形状 说明 性能 适用场景
Sphere 球形 最优 子弹、球体
Capsule 胶囊体 角色碰撞体
Box 长方体 箱子、墙壁
Plane 平面 地面
Convex Meshes 凸多边形 一般 不规则道具
Triangle Meshes 三角网格 较差 静态复杂地形
Height Fields 高度场 良好 地形

碰撞体复杂度

Triangle Meshes 仅用于静态物体,不能用于模拟(Simulating)的对象。动态物体应尽量使用 Sphere、Capsule、Box 等基础形状,或用多个基础形状组合(Aggregate)近似复杂外形。

碰撞检测

碰撞通道(Collision Channel)

UE 使用 碰撞通道(Collision Channel)碰撞响应(Collision Response) 来控制哪些物体之间发生碰撞交互。

碰撞响应有三种状态:

  • Block(阻挡):物理碰撞 + 触发事件,物体会互相推开
  • Overlap(重叠):不产生物理碰撞,但触发 OnBeginOverlap / OnEndOverlap 事件
  • Ignore(忽略):完全忽略,不碰撞也不触发事件
Text Only
1
2
3
4
5
碰撞矩阵示意(ObjectChannel vs ObjectChannel):
                Pawn    WorldDynamic    Projectile
Pawn            Block   Block           Overlap
WorldDynamic    Block   Block           Block
Projectile      Overlap Block           Ignore

碰撞查询

用于查询碰撞,查询发生的条件是一个Shape与一个碰撞通道相交。

常用的查询方式:

从一点到另一点发射一条射线,检测沿途碰撞。

C++
FHitResult HitResult;
FVector Start = GetActorLocation();
FVector End = Start + GetActorForwardVector() * 1000.f;

bool bHit = GetWorld()->LineTraceSingleByChannel(
    HitResult, Start, End, ECC_Visibility
);

if (bHit)
{
    AActor* HitActor = HitResult.GetActor();
    FVector HitPoint = HitResult.ImpactPoint;
}

用一个形状沿路径扫掠,检测碰撞体积更大的物体。

C++
1
2
3
4
5
6
7
FHitResult HitResult;
FCollisionShape Shape = FCollisionShape::MakeSphere(50.f);

bool bHit = GetWorld()->SweepSingleByChannel(
    HitResult, Start, End, FQuat::Identity,
    ECC_Pawn, Shape
);

在指定位置检测是否有物体重叠。

C++
1
2
3
4
5
6
7
TArray<FOverlapResult> Overlaps;
FCollisionShape Shape = FCollisionShape::MakeSphere(200.f);

GetWorld()->OverlapMultiByChannel(
    Overlaps, Center, FQuat::Identity,
    ECC_Pawn, Shape
);

物理材质(Physical Material)

物理材质定义表面的物理属性,影响碰撞行为:

属性 说明
Friction 摩擦系数(0 ~ 1),影响物体滑动
Restitution 弹性系数(0 ~ 1),0 = 不弹,1 = 完全弹性碰撞
Density 密度,与体积共同决定质量

物理材质 vs 材质(Material)

Physical Material 控制物理行为(摩擦、弹性),Material 控制视觉外观(颜色、纹理)。两者是独立的概念,但可以在 Material 中指定关联的 Physical Material。

物理约束(Physics Constraint)

Physics Constraint 用于约束两个刚体之间的相对运动,模拟铰链、弹簧、绳索等效果。

常见约束类型:

  • 自由度(Free):该轴向无限制
  • 锁定(Locked):该轴向完全固定
  • 受限(Limited):该轴向在指定范围内运动
应用场景 约束配置
车门铰链 Swing 1 Limited(0~90 度),其余 Locked
角色吊绳 Swing 1/2 Free,Twist Locked,配合适当 Linear Limit
车轮悬挂 Twist Free(旋转),Swing Locked,Linear Z Limited
布娃娃关节 各轴 Limited,角度根据人体骨骼设置上限
C++
1
2
3
4
5
6
7
8
// C++ 创建物理约束
UPhysicsConstraintComponent* Constraint = CreateDefaultSubobject<UPhysicsConstraintComponent>(TEXT("Constraint"));
Constraint->SetConstrainedComponents(BodyA, NAME_None, BodyB, NAME_None);

// 设置角度限制
Constraint->SetAngularSwing1Limit(EAngularConstraintMotion::ACM_Limited, 45.f);
Constraint->SetAngularSwing2Limit(EAngularConstraintMotion::ACM_Limited, 45.f);
Constraint->SetAngularTwistLimit(EAngularConstraintMotion::ACM_Locked, 0.f);

蓝图物理操作

在蓝图中可以通过以下方式操作物理:

  • AddForce / AddImpulse:对物体施加力或冲量
  • AddForce:持续力,需要每帧调用,效果与质量相关
  • AddImpulse:瞬时冲量,一次性施加
  • SetSimulatePhysics:开关物体的物理模拟(布娃娃系统常用)
  • SetPhysicsLinearVelocity / SetPhysicsAngularVelocity:直接设置速度
  • Set Physics Constraint:运行时修改约束参数

布娃娃系统

角色死亡时切换到布娃娃的典型流程:

  1. 调用 SetSimulatePhysics(true) 开启物理模拟
  2. 调用 SetAllBodiesSimulatePhysics(true) 让所有骨骼参与
  3. 调用 SetAllBodiesBelowPhysicsBlendWeight(BoneName, 1.0f) 控制特定骨骼
  4. 使用 Physics Blend Weight 在动画和物理之间插值,实现半动画半物理的效果

物理动画

基于动画和真实物理模拟插值的动画,应用到骨骼模型上。

Physical Animation Component 可以将物理模拟与动画结合:对部分骨骼施加物理力,同时保持动画驱动。典型应用:

  • 角色被击中时上半身向后倾倒,下半身保持行走动画
  • 布娃娃仅在死亡时完全接管,平时用部分物理增强表现力