UE 面试题库 · 整理版

第6章 物理与碰撞系统

本章共 22 道题,覆盖:碰撞通道与响应矩阵、射线/Sweep/Overlap 查询、物理材质、Chaos 物理引擎、物理约束与铰链、破坏系统、物理资产与布娃娃、布料与物理动画、碰撞性能优化、物理子步进、网络同步与综合设计。

一、碰撞通道与碰撞响应

1.1 碰撞通道(Collision Channel)与碰撞响应(Collision Response)

★★ 中等

考点: Collision Channel、Object Type、Collision Response(Block/Overlap/Ignore)、碰撞预设

参考答案:

  1. 通道分两类:
    • Object Channel(对象通道):定义物体"是什么",每个物理体只能有一个;默认为 WorldStatic、WorldDynamic、Pawn、PhysicsBody、Vehicle、Destructible。
    • Trace Channel(检测通道):定义检测的类型(射线/Sweep),不属于物体本身;默认为 Visibility、Camera。
  2. 三种响应的行为:
    • Block:物理引擎阻止穿透,触发 OnComponentHit,产生反作用力;
    • Overlap:不阻止穿透,触发 OnComponentBeginOverlap/EndOverlap,不产生物理力;
    • Ignore:完全无交互,不做碰撞检测。
    • 响应矩阵:Block×Block=物理碰撞;Block×Overlap=Block 方阻挡并触发 Overlap 事件;Overlap×Overlap=双向 Overlap;任一方 Ignore 即无交互。
  3. C++ 设置碰撞响应:
Mesh->SetCollisionObjectType(ECC_Pawn);
Mesh->SetCollisionResponseToChannel(ECC_Visibility, ECR_Block);
Mesh->SetCollisionResponseToAllChannels(ECR_Block);
Mesh->SetCollisionResponseToChannel(ECC_Visibility, ECR_Ignore);
Mesh->SetCollisionProfileName(FName("PhysicsActor")); // 推荐使用预设
  1. 自定义通道:Project Settings → Collision → New Object/Trace Channel;或在 DefaultEngine.ini 中配置:
[/Script/Engine.CollisionProfile]
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,DefaultResponse=ECR_Block,bTraceType=False,bStaticObject=False,Name="Projectile")
#define ECC_Projectile ECC_GameTraceChannel1
  1. 碰撞预设(Collision Profile)= Object Type + 一组响应规则打包(如 "Pawn"、"PhysicsActor"、"NoCollision")。
  2. 事件触发条件:响应不都为 Ignore;至少一方开启 GenerateOverlapEvents / bNotifyRigidBodyCollision(Hit 事件);Overlap 至少一方响应为 Overlap,Hit 至少一方为 Block。
  3. 易错点:把 Overlap 当 Hit 用、忘记开启 Generate Overlap Events;过多 Overlap 检测有性能开销。

1.2 碰撞通道(Collision Channel)的详细配置与自定义

★★★ 困难

考点: 碰撞系统配置、通道管理、通道数量限制、性能影响

参考答案:

  1. 通道数量限制:
    • Object Channel:最多 18 个(含默认 8 个),每物体只能有一个;
    • Trace Channel:最多 18 个(含默认 2 个);
    • 响应矩阵大小 = (Object + Trace Channels)²,通道越多查询开销越大。
  2. 创建自定义通道:Project Settings → Collision 新建,或在 DefaultEngine.ini 配置,C++ 中用 #define 或 UENUM 引用:
#define ECC_Projectile ECC_GameTraceChannel1
UENUM(BlueprintType)
enum class ECollisionChannel_Custom : uint8
{
    Projectile = ECC_GameTraceChannel1,
    Interactable = ECC_GameTraceChannel2,
};

void AMyProjectile::SetupCollision()
{
    Collision->SetCollisionObjectType(ECC_Projectile);
    Collision->SetCollisionResponseToChannel(ECC_Pawn, ECR_Block);
    Collision->SetCollisionResponseToChannel(ECC_Projectile, ECR_Ignore);
}
  1. 自定义预设与响应容器:
FCollisionResponseContainer Container;
Container.WorldStatic = ECR_Block;
Container.Pawn = ECR_Overlap;
GetStaticMeshComponent()->SetCollisionResponseContainer(Container);
  1. 最佳实践:限制自定义通道数量、复用现有通道;集中管理碰撞预设;对不交互物体用 Ignore;记录每个通道用途。
  2. 追问:超过 18 个 Object Channel 怎么办?可用组件标签(Component Tag)或自定义枚举扩展碰撞分类。

1.3 碰撞响应矩阵(Block/Overlap/Ignore)的设置与调试

★★★ 困难

考点: 碰撞响应配置、运行时动态修改、调试工具、常见问题

参考答案:

  1. 三种响应行为差异:
    • Block:阻隔、触发 OnComponentHit/OnActorHit、含反作用力,用于墙/地/角色;
    • Overlap:穿透、触发 Overlap 事件、无物理力,用于拾取物/触发器/伤害区域;
    • Ignore:无交互、不检测、性能最高。
  2. 响应矩阵对称:A→B 设为 Block 会自动设置 B→A 为 Block;任一方 Ignore 则无交互。
  3. 运行时动态修改:
// 无敌状态
GetCapsuleComponent()->SetCollisionResponseToChannel(ECC_Damage, ECR_Ignore);
GetMesh()->SetCollisionObjectType(ECC_Projectile);
GetMesh()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
// 单个 Actor 忽略
GetStaticMeshComponent()->IgnoreComponentWhenMoving(OtherComp, true);
  1. 调试工具:
    • 控制台:show collision、show Collision Pawn;
    • Collision Analyzer(Window → Developer Tools);
    • 代码查询:GetCollisionResponseContainer()、GetCollisionObjectType()、GetCollisionResponseToChannel(ECC_Pawn)。
  2. 常见问题排查:碰撞不生效(NoCollision / Object Type 错 / Ignore);Overlap 不触发(未开 Generate Overlap Events / 响应不含 Overlap);物理穿透(高速需 CCD、子步进);性能问题(简化碰撞体、碰撞休眠、减少 Overlap 对)。
  3. 追问:只检测敌人但不阻挡子弹的触发器 → 设为 Overlap,只对敌人通道响应 Overlap,其余 Ignore。

二、碰撞检测与查询

2.1 射线检测与 Sweep 检测

★★ 中等

考点: Line Trace、Sweep 检测、Single vs Multi、检测通道、忽略列表、性能优化

参考答案:

  1. 类型对比:
    • Line Trace:A→B 无宽度射线,最快,适合射击/视线;
    • Sphere/Box/Capsule Sweep:形状沿路径移动,可检测"粗"物体,适合近战挥舞、角色移动。
  2. Single 返回第一个命中,Multi 返回全部命中(按距离排序)。
FHitResult HitResult;
bool bHit = GetWorld()->LineTraceSingleByChannel(HitResult, Start, End, ECC_Visibility);

TArray<FHitResult> HitResults;
bool bHit2 = GetWorld()->LineTraceMultiByChannel(HitResults, Start, End, ECC_Visibility);
  1. 查询参数:AddIgnoredActor、bTraceComplex、bReturnPhysicalMaterial、TraceTag;FHitResult 含 ImpactPoint、ImpactNormal、Distance、PhysMaterial、HitActor、HitComponent、BoneName。
  2. 射击弹道检测示例(含穿透与部位伤害):
void AShooterCharacter::PerformWeaponTrace(const FVector& MuzzleLocation,
                                           const FVector& AimDirection, float WeaponRange)
{
    FVector Start = MuzzleLocation;
    FVector End = Start + AimDirection * WeaponRange;
    FCollisionQueryParams Params;
    Params.AddIgnoredActor(this);
    Params.bReturnPhysicalMaterial = true;

    FHitResult Hit;
    if (GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_WeaponTrace, Params))
    {
        ProcessHit(Hit);
        // 穿透:从命中点继续向后检测,伤害衰减
        if (bCanPenetrate)
        {
            FVector PenetrationStart = Hit.ImpactPoint + AimDirection * 1.0f;
            FHitResult PenetrationHit;
            if (GetWorld()->LineTraceSingleByChannel(PenetrationHit, PenetrationStart, End,
                                                     ECC_WeaponTrace, Params))
                ProcessHit(PenetrationHit, 0.5f);
        }
        SpawnImpactEffect(Hit);
        SpawnTracerEffect(Start, Hit.ImpactPoint);
    }
    else SpawnTracerEffect(Start, End);
}

void ProcessHit(const FHitResult& Hit, float Multiplier = 1.0f)
{
    float M = 1.0f;
    if (Hit.BoneName == FName("head")) M = 4.0f;      // 爆头
    else if (Hit.BoneName.ToString().Contains("spine")) M = 1.5f;
    UGameplayStatics::ApplyPointDamage(Hit.GetActor(), 25.0f * M * Multiplier,
        Hit.TraceEnd - Hit.TraceStart, Hit, GetController(), this, UDamageType::StaticClass());
}
  1. Sweep 应用:近战范围检测用 SweepMultiByChannel + 球体 Shape;拾取检测用 OverlapMultiByChannel。
FCollisionShape Shape;
Shape.SetSphere(MeleeRadius);
GetWorld()->SweepMultiByChannel(HitResults, Start, End, FQuat::Identity, ECC_Pawn, Shape);
  1. 频繁检测优化:降低检测频率(定时器/间隔)、通道过滤、缓存结果、AsyncLineTraceByChannel 异步检测、距离预筛选。

2.2 射线检测(Line Trace)的参数详解

★★ 中等

考点: 射线检测 API、FCollisionQueryParams 配置、性能优化

参考答案:

  1. 两种 API:LineTraceSingleByChannel(第一个命中)、LineTraceMultiByChannel(全部命中,按距离排序)。
  2. 查询参数详解:
FCollisionQueryParams Params;
Params.AddIgnoredActor(MyActor);           // 忽略 Actor
Params.bTraceComplex = true;               // 使用复杂三角网格碰撞
Params.bReturnFaceIndex = true;            // 返回碰撞三角面索引
Params.bReturnPhysicalMaterial = true;     // 返回物理材质
Params.TraceTag = FName("MyTraceTag");     // 调试标签
  1. FHitResult 解析:bBlockingHit、ImpactPoint、ImpactNormal、Distance、GetActor()、GetComponent()、BoneName、PhysMaterial->SurfaceType、FaceIndex。
  2. 高级用法:
    • LineTraceMultiByObjectType:按 Object Type 过滤,FCollisionObjectQueryParams::AddObjectTypesToQuery(ECC_Pawn);
    • LineTraceSingleByProfile:按碰撞预设检测;
    • AsyncLineTraceByChannel:异步检测返回 FTraceHandle,用 QueryTraceData 取结果。
  3. 性能优化:限制检测距离、bTraceComplex=false(用简单碰撞)、降低检测频率、Object Query 过滤、空间分区。
  4. 追问:如何检测锥形区域 → 多条 Line Trace 或 Sweep。

2.3 Sweep 检测(球体/盒子)的使用场景

★★★ 困难

考点: Sweep 检测原理、FCollisionShape、查询方式选型

参考答案:

  1. Sweep = 形状沿路径移动做碰撞检测;Line Trace 是零宽度的线,Sweep 带体积,可检测更大区域。
  2. 球体 Sweep:
GetWorld()->SweepSingleByChannel(Hit, Start, End, FQuat::Identity,
    ECC_Visibility, FCollisionShape::MakeSphere(50.0f), FCollisionQueryParams());
// 场景:武器挥砍范围、投射物碰撞、圆形区域
  1. 盒子 Sweep:FCollisionShape::MakeBox(FVector(50,50,50)),用于矩形/门/建筑结构检测。
  2. 胶囊体 Sweep:FCollisionShape::MakeCapsule(Radius, HalfHeight),用于角色移动(CMC 内部即用胶囊 Sweep)、穿越、爬坡检测。
  3. Multi Sweep:SweepMultiByChannel 返回全部命中;OverlapMultiByChannel(不移动形状只查重叠)用于爆炸范围、触发器、区域内物体查找。
  4. 选型总结:射击/视线用 Line;挥砍/投射物用 Sphere Sweep;矩形结构用 Box Sweep;角色移动用 Capsule Sweep;范围查询用 Overlap。
  5. 追问:扇形攻击范围 → 多个 Sweep 或自定义扇形碰撞体。

2.4 碰撞检测优化

★★★ 困难

考点: 简化碰撞体、空间分区、异步物理、碰撞性能分析

参考答案:

  1. 简化碰撞体(Simple Collision):用 Box/Sphere/Capsule/Convex Hull,检测 O(1) 公式计算;Complex Collision 用完整三角网格是 O(n²),仅必要处使用。
  2. 空间分区算法:
    • Sweep and Prune:按轴排序 AABB,适合数量稳定场景;
    • BVH:层次包围盒树,适合分布不均的动态场景(Chaos 默认);
    • Uniform Grid:均匀网格,适合物体大小相近场景,O(1) 查询;
    • 分层 Broad Phase:静态与动态物体分开处理。
  3. 优化策略:
    • 碰撞通道过滤 / Ignore 不交互对;
    • 禁用无关碰撞:SetCollisionEnabled(ECollisionEnabled::NoCollision);
    • 物体休眠:SetSleepThreshold,速度低于阈值自动休眠不参与检测;
    • 距离剔除:远距离 SetSimulatePhysics(false) 或降为 QueryOnly。
  4. 异步物理(Async Physics):物理计算放独立物理线程,不阻塞游戏线程,支持固定物理步长;需缓冲读取结果,可用 GetPhysicsScene()->WaitPhysics() 同步等待。
  5. 性能分析:stat physics、p.VisualizeSimulation、Physics Insights、stat collision。
  6. 延伸:CCD 防高速穿透、Physics Scene Partitioning、Physics Rewind 网络预测。

2.5 碰撞检测的 Broad Phase 与 Narrow Phase

★★★ 困难

考点: 碰撞检测两阶段原理、空间分区算法、性能优化

参考答案:

  1. 两阶段流程:
    • Broad Phase(粗筛):更新 AABB,用空间结构快速排除不可能碰撞的物体对,输出潜在碰撞对列表;
    • Narrow Phase(精检):对候选对精确检测,计算碰撞点、法线、穿透深度,生成接触流形。
  2. Broad Phase 算法:
    • SAP(Sweep and Prune):沿轴排序 AABB,O(n log n),适合均匀分布;
    • AABB Tree:层次树,动态插入/删除 O(log n);
    • Grid:网格分区,分布均匀场景 O(1)/查询。
  3. Narrow Phase 算法:
    • GJK:计算凸形状间距离,支持任意凸形体;
    • SAT(分离轴定理):检测分离轴,适合凸多边形;
    • EPA:GJK 扩展,计算穿透深度与法线;
    • Mesh vs Mesh:三角面级检测,精确但昂贵。
  4. 完成后进入约束求解(Sequential Impulse)与积分更新。
  5. 优化手段:选合适 Broad Phase 算法、简化碰撞体、通道过滤、碰撞休眠、碰撞 LOD;p.Broadphase.Show 1、stat collision 调试。
  6. 追问:为什么 Broad Phase 用 AABB 而非 OBB → AABB 计算更快,适合快速排除。

三、物理材质(Physical Material)

3.1 物理材质(Physical Material)

★★ 中等

考点: Physical Material 属性、摩擦力、弹力、表面类型、材质反馈

参考答案:

  1. Physical Material 定义物体表面物理特性:Friction(摩擦)、Restitution(弹力)、Density(密度)、Surface Type(表面类型)。
  2. 核心属性:
    • Friction 0~1:0=光滑(冰),1=高摩擦(橡胶);
    • Restitution 0~1:0=非弹性(粘土),1=完全弹性(弹力球);
    • Friction/Restitution Combine Mode:Average / Min / Multiply / Max(决定两物体碰撞时取值的规则);
    • Density 影响质量计算(Mass = Volume × Density);
    • Surface Type 自定义枚举,用于音效/特效反馈。
  3. 按表面类型配置反馈(音效 + 粒子):
void AMyActor::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor,
                     UPrimitiveComponent* OtherComp, FVector NormalImpulse,
                     const FHitResult& Hit)
{
    if (Hit.PhysMaterial.IsValid())
    {
        EPhysicalSurface S = Hit.PhysMaterial->SurfaceType;
        UGameplayStatics::PlaySoundAtLocation(this, GetImpactSound(S), Hit.ImpactPoint);
        UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), GetImpactEffect(S),
            Hit.ImpactPoint, Hit.ImpactNormal.Rotation());
    }
}
  1. 用 Surface Type 枚举(Project Settings → Physics → Physical Surface 定义 SurfaceType1=Metal 等),配合 #define SURFACE_METAL SurfaceType1 使用;Physical Material Mask 可为同一网格不同区域指定不同物理材质。
  2. 与角色移动配合:CharacterMovementComponent 中读取地面 Hit 的 PhysMaterial->SurfaceType,冰面降低 GroundFriction 与刹车减速。
  3. 高级:Friction Combine Mode、Physical Material Mask、运行时 SetPhysMaterialOverride 覆盖。

3.2 物理材质(Physical Material)的摩擦力与弹力

★★ 中等

考点: 物理材质配置、摩擦力、弹性系数、表面类型与音效

参考答案:

  1. 创建物理材质:Content Browser → Physics → Physical Material;参数示例:PM_Ice(Friction 0.1、Restitution 0.1)、PM_Rubber(0.8/0.8)、PM_Wood(0.5/0.3)。
  2. 代码创建与应用:
UPhysicalMaterial* PhysMat = NewObject<UPhysicalMaterial>();
PhysMat->Friction = 0.5f;
PhysMat->Restitution = 0.3f;
GetStaticMeshComponent()->SetPhysMaterialOverride(PhysMat);
  1. 弹跳规则:两物体碰撞的实际恢复系数 = A.Restitution × B.Restitution。
  2. 表面类型枚举(自定义 EPhysicalSurface),在走路回调用下行射线获取地面 PhysMaterial->SurfaceType,switch 选择对应脚步声/粒子。
  3. 材质混合规则:摩擦力取 Average/Min/Multiply/Max(可在项目设置配置),弹性常用乘积。
  4. 追问:不同地面脚印效果 → Surface Type 检测地面类型,生成不同脚印粒子。

四、Chaos 物理引擎基础

4.1 物理模拟基础(Chaos Physics)

★★ 中等

考点: Chaos 架构、PhysX vs Chaos、刚体模拟三阶段、物理体类型

参考答案:

  1. UE5 默认物理引擎是 Epic 自研 Chaos Physics,替代 UE4 的 PhysX(第三方库不可控、破坏/布料不原生)。Chaos 优势:原生破坏与布料、异步计算与多线程契合、确定性(Deterministic)利于网络同步、完全开源。
  2. 刚体模拟三阶段流水线:
    • Broad Phase:算 AABB,用 BVH / Sweep-and-Prune 输出潜在碰撞对;
    • Narrow Phase:GJK 判相交,EPA 算穿透深度与法线,生成 Contact Manifold;
    • Constraint Solver:Sequential Impulse 迭代求解法线冲量与摩擦力,再积分更新位姿。
  3. 物理体三种类型:
    • Static:SetSimulatePhysics(false),不被动、不移动;
    • Kinematic:代码控制移动但可影响动态体(移动平台);
    • Dynamic:SetSimulatePhysics(true),完全由物理控制,可用 SetMassOverrideInKg 覆盖质量。
  4. Chaos vs PhysX 对比要点:确定性(Chaos 可确定)、破坏原生支持、布料 Chaos Cloth、内存与源码由 UE 管理。
  5. 延伸:Chaos Destruction、Chaos Cloth、Sub-stepping、Physics Thread、Deterministic Simulation。

4.2 物理子步进(Sub-stepping)的原理

★★★ 困难

考点: 物理模拟精度、子步进配置、性能权衡、CCD

参考答案:

  1. 子步进 = 将一帧物理模拟拆成多个小步(如 16ms 一帧拆成 4×4ms),提高精度、减少高速物体穿透。
  2. 配置:
[/Script/Engine.PhysicsSettings]
bSubstepping=True
MaxSubstepDeltaTime=0.004
MaxSubsteps=4
UPhysicsSettings* PS = UPhysicsSettings::Get();
PS->bSubstepping = true;
PS->MaxSubstepDeltaTime = 0.004f;
PS->MaxSubsteps = 4;
  1. 子步进回调:FPhysSubstepCallback(OnSubstep 每子步执行)与 RegisterSubstepCallback/UnregisterSubstepCallback;也可在 Tick UseAsyncPhysicsTick 使用 Async Physics Tick。
  2. 性能影响:CPU 开销 ≈ 子步进次数 × 单次模拟开销,碰撞检测次数增加,需要更多状态缓存。
  3. 适用场景:赛车/弹球等高精度、高速物体多;不适用:移动端/性能敏感/物理简单游戏。
  4. 替代方案:CCD(连续碰撞检测)(SetUseCCD(true),开销比子步进小)、加厚碰撞体、限制最大速度、碰撞预测。
  5. 追问:不启用子步进防穿透 → CCD 或加大碰撞体。

五、物理约束(Physics Constraint)与铰链

5.1 物理约束(Physics Constraint)

★★ 中等

考点: Physics Constraint、自由度限制、马达驱动、铰链/滑块/球窝关节

参考答案:

  1. Physics Constraint 连接两个物理体并限制相对运动,控制 6 个自由度(3 平移 + 3 旋转),每个自由度可设 Free / Limited / Locked。
  2. 铰链关节(门):锁定 3 个平移自由度,Swing1 锁定、Swing2 Limited(如 90°)、Twist 锁定,仅允许绕轴旋转:
DoorHinge->SetConstrainedComponents(DoorFrame, NAME_None, Door, NAME_None);
DoorHinge->SetLinearXLimit(ELinearConstraintMotion::LCM_Locked, 0);
DoorHinge->SetLinearYLimit(ELinearConstraintMotion::LCM_Locked, 0);
DoorHinge->SetLinearZLimit(ELinearConstraintMotion::LCM_Locked, 0);
DoorHinge->SetAngularSwing1Limit(EAngularConstraintMotion::ACM_Locked, 0);
DoorHinge->SetAngularSwing2Limit(EAngularConstraintMotion::ACM_Limited, 90.0f);
DoorHinge->SetAngularTwistLimit(EAngularConstraintMotion::ACM_Locked, 0);
  1. 滑块关节(抽屉):仅 LinearX LCM_Limited 30,其余平移与全部旋转 Locked。
  2. 绳索:多段细长刚体 + 每个接点加约束,各关节 Swing Limited 45°、Twist Limited,逐段 SetConstrainedComponents 串接。
  3. 马达(Motor)驱动:用 Spring(Stiffness)+ Damping + ForceLimit 模型,设定目标位置/旋转主动驱动(自动门、电梯):
DoorHinge->SetAngularDriveMode(EAngularDriveMode::TwistAndSwing);
DoorHinge->SetAngularDriveParams(1000.0f, 100.0f, 0.0f);
DoorHinge->SetAngularOrientationTarget(FRotator(0, 90, 0));
ElevatorConstraint->SetLinearDriveParams(5000.0f, 500.0f, 0.0f);
ElevatorConstraint->SetLinearPositionTarget(FVector(0, 0, 500.0f));
  1. 易错点:忘记设置 Constraint 的参考框架(Local Frame)导致旋转轴/限制方向错误;延伸:Breakable Constraint(超阈值自动断裂)、Ragdoll 骨骼约束。

5.2 物理约束(Physics Constraint)的 6 个自由度

★★★ 困难

考点: 自由度控制、关节模拟、驱动模式(Drive Mode)

参考答案:

  1. 6 个自由度:平移 Linear X/Y/Z(前后/左右/上下)、旋转 Swing1(绕X 俯仰)、Swing2(绕Y 偏航)、Twist(绕Z 翻滚);每个可 Free / Limited / Locked。
  2. 门(铰链):3 平移 Locked,Swing1 Locked、Swing2 Limited 90°、Twist Locked。
  3. 滑轨:仅 X 平移 Limited(如 100),其余平移与全部旋转 Locked。
  4. 球窝关节(布娃娃):平移全 Locked,Swing1/Swing2 Limited 45°、Twist Limited 30°。
  5. 驱动模式(Drive Mode)= 主动驱动而非被动限制,含 Linear Drive 与 Angular Drive:
Constraint->SetLinearDriveParams(1000.0f, 100.0f, 0.0f);   // Spring, Damping, ForceLimit
Constraint->SetLinearPositionTarget(FVector(0, 0, 100.0f));
Constraint->SetAngularDriveParams(1000.0f, 100.0f, 0.0f);
Constraint->SetAngularOrientationTarget(FRotator(0, 90, 0));
Constraint->SetLinearPositionDrive(true, true, true);
Constraint->SetAngularOrientationDrive(true, true);
  1. 追问:自动关闭的门 → Angular Drive 模式 + 目标旋转与弹簧阻尼参数。

六、破坏系统(Destruction)

6.1 Chaos 破坏系统(Destruction)原理

★★★ 困难

考点: Chaos Destruction、Voronoi 分裂、多层级破坏、碎片生命周期、性能优化

参考答案:

  1. 工作流:用 Geometry Collection 定义可破坏物体 → 编辑器 Fracture 分裂 → 设破坏参数 → 运行时受力/伤害触发 → 碎片成为独立物理体。
  2. Voronoi 分裂:物体内随机种 N 个种子点,按最近种子点划分空间成碎片;特点:形状自然、大小可控、支持非均匀(局部加密度)。其他模式:Planar、Cluster、Radial、Slice、Brick。
  3. 多层级破坏:Level 0 完整 → Level 1 大块 → Level 2 中块 → Level 3 小块,逐级触发 ApplyDamage,层级越深伤害需求越大。
  4. C++ 触发破坏:
GeometryCollection->ApplyDamage(0,          // Level
    Damage, ImpactPoint,
    FVector::ZeroVector, 100.0f);           // 冲击方向, 冲量强度
GeometryCollection->ApplyExternalStrain(0, Origin, Force, Radius);
  1. 碎片生命周期:SetDebrisTimeout 自动销毁、SetMaxClusterCount 上限淘汰、SetDistanceCulling 距离剔除、Cluster Union 远距离合并、物理休眠。
  2. 性能优化:Cluster(大块套小块)分层、碎片用简单碰撞体、异步物理、碎片池(预创建重用避免频繁创建销毁)、破坏 LOD。
  3. 追问:Geometry Collection vs Static Mesh 区别;破坏大场景优先用 Cluster + 碎片池。

6.2 Chaos 破坏系统(GeometryCollection)的使用

★★★ 困难

考点: GeometryCollection、碎片物理、破坏事件、性能优化

参考答案:

  1. Chaos 破坏系统基于 Geometry Collection(几何集合),与 Chaos 物理深度集成;核心概念:GeometryCollection、Fracture、Fragment、Damage。
  2. 创建流程:导入网格 → 右键 Create Geometry Collection → 编辑器选破碎模式(Voronoi/Planar/Cluster/Custom)→ 调参 → 生成碎片;或用 Chaos Destruction 工具。
  3. C++ 使用:
UCLASS()
class ADestructibleActor : public AActor
{
    UPROPERTY(VisibleAnywhere)
    UGeometryCollectionComponent* GeometryCollection;
    ADestructibleActor()
    {
        GeometryCollection = CreateDefaultSubobject<UGeometryCollectionComponent>(TEXT("GC"));
        RootComponent = GeometryCollection;
        GeometryCollection->SetSimulatePhysics(true);
        GeometryCollection->SetEnableDamagePropagation(true);
    }
    void ApplyDamage(FVector ImpactPoint, float Damage)
    {
        GeometryCollection->ApplyDamage(0, Damage, ImpactPoint, FVector::ZeroVector, 100.0f);
    }
};
  1. 破碎模式:Voronoi(玻璃/石头)、Planar(木板/墙)、Cluster(建筑/大物体层级破碎)、Custom(Houdini 艺术控制)。
  2. 碎片事件与生命周期:OnChaosBreakEvent(含 FChaosBreakEvent:位置、冲量)触发粒子/音效;SetFragmentDestroyTimeout 超时销毁。
  3. 性能优化:SetFragmentMaxCount 数量上限、碎片 LOD、碎片池、用简单碰撞、SetCollisionBetweenFragments(false) 禁用碎片间碰撞、异步物理。

七、物理资产与布娃娃

7.1 布料模拟与物理资产(Physics Asset)

★★★ 困难

考点: Chaos Cloth 工作流、布料约束、Physics Asset 结构、布娃娃

参考答案:

  1. UE5 用 Chaos Cloth(替代 NvCloth),工作流:Skeletal Mesh 标记布料顶点 → 设约束与参数 → 每帧模拟 → 结果影响网格顶点;支持衣物、头发、旗帜等。
  2. 布料约束:
    • Max Distance:顶点偏离绑定姿态的最大距离(权重 1=完全移动,0=固定如肩部);
    • Backstop(距离/半径):背面球形区域防止穿透身体;
    • Self Collision:布料自碰撞,开销大慎用;
    • World Collision:与场景物体碰撞(用简化碰撞体);
    • Tether:系绳约束防过度拉伸。
  3. 布料参数:Wind、Gravity、Damping、Friction、Mass、Inertia Scale;编辑器用 Cloth Paint 刷权重、Cloth Config 面板调参。
  4. Physics Asset 结构:Body Setup(每骨骼的 Sphere/Capsule/Box/Convex 碰撞体)+ Constraint Setup(骨骼间约束:角/线限制与马达);每骨骼 0 或 1 个碰撞体。
  5. Physics Asset 用途:布娃娃(Ragdoll)、物理碰撞检测、布料身体碰撞、死亡动画物理混合。
  6. 布娃娃启用:
GetMesh()->SetAnimationMode(EAnimationMode::PhysicsSimulation);
GetMesh()->SetSimulatePhysics(true);
GetMesh()->SetAllBodiesBelowSimulatePhysics(FName("pelvis"), true, true);
GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
  1. 物理混合:SetAllBodiesPhysicsBlendWeight(0.5f)(0=纯动画,1=纯物理);部分身体动力学(下半身物理+上半身动画)。
  2. 布料与身体配合:Physics Asset 定义身体碰撞体(略大于视觉网格留布料空间),布料用它做世界碰撞。

7.2 物理资产(Physics Asset)与布娃娃效果

★★★ 困难

考点: 物理资产配置、布娃娃系统、骨骼物理、物理混合

参考答案:

  1. Physics Asset = 骨骼网格体的物理表示:每骨骼的碰撞体 + 骨骼间约束 + 物理属性,用于布娃娃、物理模拟、碰撞检测。
  2. 碰撞体类型选型:Capsule(四肢/躯干最常用)、Sphere(头/关节)、Box(骨盆/躯干)、Convex Hull(复杂形状);参数含 Size、相对骨骼位置/旋转、Physics Type。
  3. 启用布娃娃:
void AMyCharacter::EnableRagdoll()
{
    GetMesh()->SetAnimationMode(EAnimationMode::AnimationCustomMode);
    GetMesh()->SetAllBodiesSimulatePhysics(true);
    GetMesh()->SetSimulatePhysics(true);
    GetMesh()->WakeAllRigidBodies();
    GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
    Mesh->SetAllBodiesPhysicsBlendWeight(1.0f);
    Mesh->SetAllBodiesNotifyRigidBodyCollision(true);
}
  1. 物理混合(Physics Blend):权重 0=完全动画,1=完全物理,0.5=各半;SetAllBodiesBelowPhysicsBlendWeight(FName("pelvis"), 1.0f) 控制范围。
  2. 受击反馈实现:FindClosestBone(ImpactPoint) 找最近骨骼 → 临时设混合权重 → AddForceToAllBodiesBelow 加冲量 → 定时恢复纯动画。
  3. Physics Asset 编辑器:碰撞体编辑、约束编辑(自由度限制)、实时模拟预览、自动生成碰撞体等工具。
  4. 追问:受击物理反馈 → Physics Blend 临时启用物理,加冲量后逐渐恢复动画。

八、布料与物理动画

8.1 Chaos Cloth 布料系统的使用

★★★ 困难

考点: 布料模拟、Chaos Cloth、参数配置、布料与动画配合

参考答案:

  1. Chaos Cloth 基于 Chaos 物理引擎实时布料模拟,支持风力、碰撞、约束;应用:角色衣物(披风/裙子/围巾)、装饰布料、可撕裂布料。
  2. 配置流程:Skeletal Mesh 启用 Cloth → 选模拟顶点 → Cloth Painting Tool 刷权重(0=固定,1=完全模拟)→ 调整参数。
  3. 参数分类:
    • 物理:Mass、Damping、Stiffness、Stretching / Bending 刚度;
    • 碰撞:Collision Thickness、Self Collision Distance / Stiffness;
    • 约束:Max Distance、Backstop Distance / Radius;
    • 环境:Gravity Scale、Wind Velocity、Air Drag。
  4. 布料与动画配合:骨骼驱动(附加骨骼,骨骼动带动布料)、身体碰撞体防穿透、约束限制范围。
  5. 运行动态调整(AnimBP NativeUpdateAnimation):按角色速度 lerp 阻尼、按移动方向设置风速。
  6. 性能优化:降顶点数/布料 LOD、降低更新频率、简化碰撞、合理约束、远距离禁用布料。

8.2 物理动画系统(Physical Animation Component)

★★★ 困难

考点: 物理动画混合、物理驱动动画、受击反馈、布娃娃过渡

参考答案:

  1. Physical Animation Component = 物理与动画的混合系统:部分骨骼动画驱动、部分物理驱动,可动态调强度;用于受击反馈、布娃娃平滑过渡、物理交互。
  2. 参数:
    • Orientation Strength:朝向动画姿态的强度;
    • Angular Velocity Strength:角速度匹配强度(平滑度);
    • Position / Velocity Strength:位置/速度匹配强度;
    • bIsLocalSimulation:本地空间 vs 世界空间计算。
  3. 配置示例:
FPhysicalAnimationData PhysAnimData;
PhysAnimData.bIsLocalSimulation = false;
PhysAnimData.OrientationStrength = 1000.0f;
PhysAnimData.AngularVelocityStrength = 100.0f;
PhysAnimData.PositionStrength = 1000.0f;
PhysAnimData.VelocityStrength = 100.0f;
PhysicalAnimationComponent->SetSkeletalMeshComponent(GetMesh());
PhysicalAnimationComponent->ApplyPhysicalAnimationSettings(FName("spine_01"), PhysAnimData);
  1. 受击反馈:FindClosestBone → 对受击骨骼设较低强度 + SetAllBodiesBelowSimulatePhysics(true) + AddImpulseAtLocation → 延迟恢复强度、关闭物理。
  2. 布娃娃过渡:分步逐渐把强度 lerp 到 0(模拟"失去控制"),结束 EnableRagdoll,实现平滑过渡。
  3. 与动画蓝图配合:按速度计算 StrengthMultiplier(Clamp 0.5~1.0)动态更新参数。
  4. 追问:被击飞效果 → 降低物理动画强度 + 添加冲量 + 逐渐恢复。

九、物理网络同步与综合设计

9.1 物理模拟的网络同步

★★★ 困难

考点: 物理网络同步、预测与校正、状态压缩、一致性

参考答案:

  1. 挑战:物理非确定性(浮点误差)、网络延迟导致状态不一致、预测错误需回滚、带宽限制。
  2. 三种策略:
    • 服务端权威:全部物理在服务端计算,客户端只显示,一致性好但延迟高;
    • 客户端预测:客户端预测 + 服务端校正,响应快但可能回滚;
    • 确定性物理:定点数 + 确定性算法保证各端一致,无需同步但实现复杂。
  3. 客户端预测、服务端校正:
// 客户端预测
PredictedPosition = CurrentPosition + CurrentVelocity * DeltaTime;
// 服务端校正:误差超阈值时 VInterpTo 插值到正确位置并修正速度
if (PositionError > CorrectionThreshold)
{
    CurrentPosition = FMath::VInterpTo(CurrentPosition, ServerPosition,
        GetWorld()->GetDeltaSeconds(), CorrectionSpeed);
    CurrentVelocity = ServerVelocity;
}
  1. 状态压缩:用 FVector_NetQuantize 量化位置/速度,FRotator::SerializeCompressed 压缩旋转,自定义 NetSerialize 减少带宽。
  2. 同步频率:仅当位置/速度变化超阈值才同步(PositionDelta > PositionThreshold),插值平滑避免跳变,按优先级控制同步频率。
  3. 优化:减少同步频率、插值、优先级排序、量化压缩、按需预测、物理 LOD。
  4. 追问:物理回滚 → 需保存物理历史状态,校正时回滚到正确状态(结合 Physics Rewind)。

9.2 物理系统综合设计题

★★★ 困难

考点: 物理系统整体架构设计、性能与效果权衡、多人游戏物理同步

参考答案:

  1. 分层架构:Projectile 系统、Destruction 系统、Vehicle Physics 统一由 Physics Manager 管理,下接 Collision、Chaos、Network Sync,外层是优化层(LOD、碎片池、异步物理、距离剔除)。
  2. 子弹物理:UProjectileMovementComponent(初速 + ProjectileGravityScale 弹道下坠);碰撞回调用穿透计数 + 衰减伤害(Math::Pow(0.6f, PenetrationCount))+ 穿透后偏转减速。
  3. 爆炸系统:SphereOverlapActors 找范围内 Actor,ApplyRadialDamage 按距离衰减;OverlapMultiByChannel(ECC_PhysicsBody) 对模拟体 AddImpulse 衰减冲击力;对含 GeometryCollection 的 Actor ApplyDamage;再生成特效与相机震动。
  4. 载具:UE5 用 UChaosWheeledVehicleMovementComponent/AWheeledVehiclePawn,配置 WheelSetups、引擎 TorqueCurve、变速箱齿轮;碰撞按 Dot(GetVelocity(), -ImpactNormal) 判定高速碰撞并结算伤害。
  5. 网络同步:子弹——客户端射线预测 + 服务端重跑验证(容差检查),成功则 Multicast 特效;爆炸/破坏——服务端权威计算,Multicast 参数/破坏状态到客户端;布娃娃——死亡时服务端切换并 Multicast 初始骨盆位姿。
  6. 性能保障 60fps:
    • 物理 LOD:按距离禁用物理 / 简化碰撞 / 完整物理(<5000 近距离完整);
    • 碎片池预创建重用;
    • 异步物理独立线程、碰撞检测频率控制;
    • 物理休眠(速度低自动休眠);
    • 破坏 LOD(远处简化/禁用)、爆炸影响物体数上限。
  7. 关键难点:服务端权威 + 客户端预测的物理一致性与回滚;三大优化手段:物理 LOD、碎片池、异步物理。