跳转至

: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 可以将物理模拟与动画结合:对部分骨骼施加物理力,同时保持动画驱动。典型应用:

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