ue-physics-collision

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

UE Physics & Collision

UE 物理与碰撞系统

You are an expert in Unreal Engine's physics and collision systems, including collision channels, trace queries, collision events, physics bodies, and the Chaos physics engine.

您是Unreal Engine物理与碰撞系统的专家,涵盖碰撞通道、轨迹查询、碰撞事件、物理刚体以及Chaos物理引擎等内容。

Step 1: Read Project Context

步骤1:读取项目上下文

Read
.agents/ue-project-context.md
to confirm:
  • UE version (Chaos is the default physics backend from UE 5.0; PhysX was deprecated)
  • Which modules need
    "PhysicsCore"
    and
    "Engine"
    in their
    Build.cs
  • Whether the project uses skeletal meshes with physics assets, or primarily static mesh collision
  • Dedicated server targets (affects whether physics simulation should run server-side)

读取
.agents/ue-project-context.md
以确认:
  • UE版本(从UE 5.0开始,Chaos是默认物理后端;PhysX已被弃用)
  • 哪些模块需要在
    Build.cs
    中添加
    "PhysicsCore"
    "Engine"
    依赖
  • 项目是否使用带有物理资源的骨骼网格体,还是主要使用静态网格体碰撞
  • 专用服务器目标(影响物理模拟是否应在服务器端运行)

Step 2: Identify the Need

步骤2:明确需求

Ask which area applies if not stated:
  1. Collision setup — channels, profiles, responses on components
  2. Trace queries — line traces, sweeps, overlap queries for gameplay logic
  3. Collision events — OnComponentHit, OnBeginOverlap, OnEndOverlap delegates
  4. Physics simulation — rigid body sim, forces, impulses, damping, constraints
  5. Physical materials — friction, restitution, surface type detection

若未说明具体场景,请询问用户属于以下哪个领域:
  1. 碰撞设置 — 组件的通道、配置文件、响应规则
  2. 轨迹查询 — 用于游戏逻辑的线轨迹、扫掠、重叠查询
  3. 碰撞事件 — OnComponentHit、OnBeginOverlap、OnEndOverlap委托
  4. 物理模拟 — 刚体模拟、力、冲量、阻尼、约束
  5. 物理材质 — 摩擦力、弹性、表面类型检测

Collision Channels & Profiles

碰撞通道与配置文件

ECollisionChannel — built-in channels

ECollisionChannel — 内置通道

cpp
ECC_WorldStatic, ECC_WorldDynamic, ECC_Pawn, ECC_PhysicsBody,
ECC_Vehicle, ECC_Destructible               // object channels (what an object IS)
ECC_Visibility, ECC_Camera                  // trace channels (used for queries)
// Custom: ECC_GameTraceChannel1..ECC_GameTraceChannel18
Responses:
ECR_Ignore
/
ECR_Overlap
(events, no block) /
ECR_Block
(physical block + events).
Built-in profiles:
BlockAll
,
BlockAllDynamic
,
OverlapAll
,
OverlapAllDynamic
,
Pawn
,
PhysicsActor
,
NoCollision
.
cpp
ECC_WorldStatic, ECC_WorldDynamic, ECC_Pawn, ECC_PhysicsBody,
ECC_Vehicle, ECC_Destructible               // 对象通道(定义物体的类型)
ECC_Visibility, ECC_Camera                  // 轨迹通道(用于查询)
// 自定义通道:ECC_GameTraceChannel1..ECC_GameTraceChannel18
响应规则
ECR_Ignore
(忽略)/
ECR_Overlap
(重叠,触发事件但不阻挡)/
ECR_Block
(物理阻挡+触发事件)。
内置配置文件
BlockAll
BlockAllDynamic
OverlapAll
OverlapAllDynamic
Pawn
PhysicsActor
NoCollision

Setting Collision in C++

在C++中设置碰撞

cpp
MyMesh->SetCollisionProfileName(TEXT("BlockAll"));        // preferred — sets all at once
MyMesh->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
// ECollisionEnabled: NoCollision | QueryOnly | PhysicsOnly | QueryAndPhysics
MyMesh->SetCollisionObjectType(ECC_PhysicsBody);
MyMesh->SetCollisionResponseToAllChannels(ECR_Block);
MyMesh->SetCollisionResponseToChannel(ECC_Pawn, ECR_Overlap);
MyMesh->SetCollisionResponseToChannel(ECC_Camera, ECR_Ignore);
cpp
MyMesh->SetCollisionProfileName(TEXT("BlockAll"));        // 推荐方式——一次性设置所有规则
MyMesh->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
// ECollisionEnabled枚举值:NoCollision | QueryOnly | PhysicsOnly | QueryAndPhysics
MyMesh->SetCollisionObjectType(ECC_PhysicsBody);
MyMesh->SetCollisionResponseToAllChannels(ECR_Block);
MyMesh->SetCollisionResponseToChannel(ECC_Pawn, ECR_Overlap);
MyMesh->SetCollisionResponseToChannel(ECC_Camera, ECR_Ignore);

Object Type Channels vs Trace Channels

对象类型通道 vs 轨迹通道

Object type channels describe what an actor IS (Pawn, WorldDynamic, Vehicle). Every component has exactly one object type. Trace channels are used for queries — they define what a trace is LOOKING FOR (Visibility, Camera, Weapon). This distinction determines which query function to use:
ByObjectType
matches the target's object type channel;
ByChannel
uses the querier's trace channel and checks responses. Most gameplay traces use trace channels (
ECC_Visibility
, custom
Weapon
); overlap queries for "find all pawns" use object type (
ECC_Pawn
).
对象类型通道描述Actor的类型(Pawn、WorldDynamic、Vehicle)。每个组件只能有一个对象类型。轨迹通道用于查询——定义轨迹要检测的目标(Visibility、Camera、Weapon)。这种区别决定了要使用的查询函数:
ByObjectType
匹配目标的对象类型通道;
ByChannel
使用查询者的轨迹通道并检查响应规则。大多数游戏玩法轨迹使用轨迹通道(
ECC_Visibility
、自定义
Weapon
通道);“查找所有Pawn”的重叠查询使用对象类型(
ECC_Pawn
)。

Custom Channels — DefaultEngine.ini

自定义通道 — DefaultEngine.ini

ini
[/Script/Engine.CollisionProfile]
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,DefaultResponse=ECR_Block,bTraceType=True,bStaticObject=False,Name="Weapon")
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel2,DefaultResponse=ECR_Block,bTraceType=False,bStaticObject=False,Name="Interactable")
+Profiles=(Name="Interactable",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Interactable",CustomResponses=((Channel="Weapon",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Block)))
bTraceType=True
= trace channel;
bTraceType=False
= object type channel. They use separate query functions.
See
references/collision-channel-setup.md
for full profile examples.

ini
[/Script/Engine.CollisionProfile]
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,DefaultResponse=ECR_Block,bTraceType=True,bStaticObject=False,Name="Weapon")
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel2,DefaultResponse=ECR_Block,bTraceType=False,bStaticObject=False,Name="Interactable")
+Profiles=(Name="Interactable",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Interactable",CustomResponses=((Channel="Weapon",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Block)))
bTraceType=True
= 轨迹通道;
bTraceType=False
= 对象类型通道。它们使用不同的查询函数。
完整的配置文件示例请查看
references/collision-channel-setup.md

Trace Queries

轨迹查询

FCollisionQueryParams

FCollisionQueryParams

cpp
FCollisionQueryParams Params;
Params.TraceTag                = TEXT("WeaponTrace"); // for profiling/debug
Params.bTraceComplex           = false;  // false=simple hull (fast); true=per-poly (expensive)
Params.bReturnPhysicalMaterial = true;   // populates Hit.PhysMaterial
Params.bReturnFaceIndex        = false;  // expensive, only when needed
Params.AddIgnoredActor(this);
Params.AddIgnoredComponent(MyComp);
cpp
FCollisionQueryParams Params;
Params.TraceTag                = TEXT("WeaponTrace"); // 用于性能分析/调试
Params.bTraceComplex           = false;  // false=简单碰撞 hull(快速); true=逐多边形检测(性能开销大)
Params.bReturnPhysicalMaterial = true;   // 填充Hit.PhysMaterial字段
Params.bReturnFaceIndex        = false;  // 性能开销大,仅在需要时启用
Params.AddIgnoredActor(this);
Params.AddIgnoredComponent(MyComp);

World-Level Trace Functions (C++) — from
WorldCollision.h
via
UWorld

世界级轨迹函数(C++)—— 来自
WorldCollision.h
,通过
UWorld
调用

cpp
FHitResult Hit;
// By trace channel
GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_Visibility, Params);
GetWorld()->LineTraceMultiByChannel(Hits, Start, End, ECC_Visibility, Params);
// By object type
FCollisionObjectQueryParams ObjParams(ECC_PhysicsBody);
ObjParams.AddObjectTypesToQuery(ECC_WorldDynamic);
GetWorld()->LineTraceSingleByObjectType(Hit, Start, End, ObjParams, Params);
// By profile
GetWorld()->LineTraceSingleByProfile(Hit, Start, End, TEXT("BlockAll"), Params);
cpp
FHitResult Hit;
// 按轨迹通道查询
GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_Visibility, Params);
GetWorld()->LineTraceMultiByChannel(Hits, Start, End, ECC_Visibility, Params);
// 按对象类型查询
FCollisionObjectQueryParams ObjParams(ECC_PhysicsBody);
ObjParams.AddObjectTypesToQuery(ECC_WorldDynamic);
GetWorld()->LineTraceSingleByObjectType(Hit, Start, End, ObjParams, Params);
// 按配置文件查询
GetWorld()->LineTraceSingleByProfile(Hit, Start, End, TEXT("BlockAll"), Params);

Sweep Queries — FCollisionShape (from
CollisionShape.h
)

扫掠查询 — FCollisionShape(来自
CollisionShape.h

cpp
FCollisionShape Sphere  = FCollisionShape::MakeSphere(30.f);
FCollisionShape Box     = FCollisionShape::MakeBox(FVector(50.f, 50.f, 50.f));
FCollisionShape Capsule = FCollisionShape::MakeCapsule(34.f, 88.f); // radius, half-height

GetWorld()->SweepSingleByChannel(Hit, Start, End, FQuat::Identity, ECC_Pawn, Sphere, Params);
GetWorld()->SweepMultiByChannel(Hits, Start, End, FQuat::Identity, ECC_Pawn, Sphere, Params);
GetWorld()->SweepSingleByObjectType(Hit, Start, End, FQuat::Identity, ObjParams, Sphere, Params);
GetWorld()->SweepSingleByProfile(Hit, Start, End, FQuat::Identity, TEXT("Pawn"), Sphere, Params);
cpp
FCollisionShape Sphere  = FCollisionShape::MakeSphere(30.f);
FCollisionShape Box     = FCollisionShape::MakeBox(FVector(50.f, 50.f, 50.f));
FCollisionShape Capsule = FCollisionShape::MakeCapsule(34.f, 88.f); // 半径,半高

GetWorld()->SweepSingleByChannel(Hit, Start, End, FQuat::Identity, ECC_Pawn, Sphere, Params);
GetWorld()->SweepMultiByChannel(Hits, Start, End, FQuat::Identity, ECC_Pawn, Sphere, Params);
GetWorld()->SweepSingleByObjectType(Hit, Start, End, FQuat::Identity, ObjParams, Sphere, Params);
GetWorld()->SweepSingleByProfile(Hit, Start, End, FQuat::Identity, TEXT("Pawn"), Sphere, Params);

Overlap Queries

重叠查询

cpp
TArray<FOverlapResult> Overlaps;
GetWorld()->OverlapMultiByObjectType(Overlaps, Center, FQuat::Identity,
    FCollisionObjectQueryParams(ECC_Pawn), FCollisionShape::MakeSphere(500.f), Params);
for (const FOverlapResult& R : Overlaps) { AActor* A = R.GetActor(); }

// By trace channel (uses channel responses, not object type matching):
GetWorld()->OverlapMultiByChannel(
    Overlaps, Center, FQuat::Identity, ECC_Pawn,
    FCollisionShape::MakeSphere(Radius), QueryParams);
cpp
TArray<FOverlapResult> Overlaps;
GetWorld()->OverlapMultiByObjectType(Overlaps, Center, FQuat::Identity,
    FCollisionObjectQueryParams(ECC_Pawn), FCollisionShape::MakeSphere(500.f), Params);
for (const FOverlapResult& R : Overlaps) { AActor* A = R.GetActor(); }

// 按轨迹通道查询(使用通道响应规则,而非对象类型匹配):
GetWorld()->OverlapMultiByChannel(
    Overlaps, Center, FQuat::Identity, ECC_Pawn,
    FCollisionShape::MakeSphere(Radius), QueryParams);

FHitResult — Key Fields

FHitResult — 关键字段

cpp
Hit.bBlockingHit;          // true if blocking
Hit.ImpactPoint;           // world space contact point
Hit.ImpactNormal;          // surface normal
Hit.Distance;              // from Start to impact
Hit.BoneName;              // skeletal mesh bone
Hit.GetActor();
Hit.GetComponent();
// Physical material (requires bReturnPhysicalMaterial=true):
if (UPhysicalMaterial* M = Hit.PhysMaterial.Get())
    EPhysicalSurface S = UPhysicalMaterial::DetermineSurfaceType(M);
cpp
Hit.bBlockingHit;          // 若为true表示发生阻挡
Hit.ImpactPoint;           // 世界空间中的接触点
Hit.ImpactNormal;          // 表面法线
Hit.Distance;              // 从起点到碰撞点的距离
Hit.BoneName;              // 骨骼网格体的骨骼名称
Hit.GetActor();
Hit.GetComponent();
// 物理材质(需要bReturnPhysicalMaterial=true):
if (UPhysicalMaterial* M = Hit.PhysMaterial.Get())
    EPhysicalSurface S = UPhysicalMaterial::DetermineSurfaceType(M);

Blueprint-Layer Traces (UKismetSystemLibrary)

蓝图层轨迹(UKismetSystemLibrary)

cpp
#include "Kismet/KismetSystemLibrary.h"
TArray<AActor*> Ignore = { this };
// LineTrace with debug draw (ETraceTypeQuery maps to ECollisionChannel)
UKismetSystemLibrary::LineTraceSingle(this, Start, End,
    ETraceTypeQuery::TraceTypeQuery1, false, Ignore, EDrawDebugTrace::ForDuration, Hit, true);
// SphereTrace
UKismetSystemLibrary::SphereTraceSingle(this, Start, End, 50.f,
    ETraceTypeQuery::TraceTypeQuery1, false, Ignore, EDrawDebugTrace::ForOneFrame, Hit, true);
// By profile
UKismetSystemLibrary::LineTraceSingleByProfile(this, Start, End,
    TEXT("BlockAll"), false, Ignore, EDrawDebugTrace::None, Hit, true);
cpp
#include "Kismet/KismetSystemLibrary.h"
TArray<AActor*> Ignore = { this };
// 带调试绘制的线轨迹(ETraceTypeQuery映射到ECollisionChannel)
UKismetSystemLibrary::LineTraceSingle(this, Start, End,
    ETraceTypeQuery::TraceTypeQuery1, false, Ignore, EDrawDebugTrace::ForDuration, Hit, true);
// 球形轨迹
UKismetSystemLibrary::SphereTraceSingle(this, Start, End, 50.f,
    ETraceTypeQuery::TraceTypeQuery1, false, Ignore, EDrawDebugTrace::ForOneFrame, Hit, true);
// 按配置文件查询
UKismetSystemLibrary::LineTraceSingleByProfile(this, Start, End,
    TEXT("BlockAll"), false, Ignore, EDrawDebugTrace::None, Hit, true);

Async Traces

异步轨迹

cpp
FTraceHandle Handle = GetWorld()->AsyncLineTraceByChannel(
    EAsyncTraceType::Single, Start, End, ECC_Visibility, Params);
// Read next frame:
FTraceDatum Datum;
if (GetWorld()->QueryTraceData(Handle, Datum) && Datum.OutHits.Num() > 0)
    FHitResult& Hit = Datum.OutHits[0];
cpp
FTraceHandle Handle = GetWorld()->AsyncLineTraceByChannel(
    EAsyncTraceType::Single, Start, End, ECC_Visibility, Params);
// 下一帧读取结果:
FTraceDatum Datum;
if (GetWorld()->QueryTraceData(Handle, Datum) && Datum.OutHits.Num() > 0)
    FHitResult& Hit = Datum.OutHits[0];

Debug Visualization

调试可视化

cpp
#if ENABLE_DRAW_DEBUG
DrawDebugLine(GetWorld(), Start, End, FColor::Red, false, 2.f);
DrawDebugSphere(GetWorld(), HitResult.ImpactPoint, 10.f, 12, FColor::Green, false, 2.f);
#endif
DrawDebugLine
/
DrawDebugSphere
are from
DrawDebugHelpers.h
. Wrap in
ENABLE_DRAW_DEBUG
so they compile out in shipping builds. The bool param is
bPersistentLines
; the float param is
LifeTime
in seconds.
See
references/trace-patterns.md
for full gameplay patterns (hitscan, melee sweep, AoE, ground detection, async sensors).

cpp
#if ENABLE_DRAW_DEBUG
DrawDebugLine(GetWorld(), Start, End, FColor::Red, false, 2.f);
DrawDebugSphere(GetWorld(), HitResult.ImpactPoint, 10.f, 12, FColor::Green, false, 2.f);
#endif
DrawDebugLine
/
DrawDebugSphere
来自
DrawDebugHelpers.h
。用
ENABLE_DRAW_DEBUG
包裹,这样在发布版本中会被编译移除。布尔参数是
bPersistentLines
(是否持久显示线条);浮点参数是
LifeTime
(显示时长,单位为秒)。
完整的游戏玩法模式(射线检测、近战扫掠、范围效果、地面检测、异步传感器)请查看
references/trace-patterns.md

Collision Events

碰撞事件

Delegate declarations from
PrimitiveComponent.h
:
  • OnComponentHit
    (HitComp, OtherActor, OtherComp, NormalImpulse, FHitResult)
    — physics collision
  • OnComponentBeginOverlap
    (OverlappedComp, OtherActor, OtherComp, OtherBodyIndex, bFromSweep, SweepResult)
  • OnComponentEndOverlap
    (OverlappedComp, OtherActor, OtherComp, OtherBodyIndex)
cpp
// Hit events (physics collision)
MyMesh->SetNotifyRigidBodyCollision(true);  // "Simulation Generates Hit Events"
MyMesh->OnComponentHit.AddDynamic(this, &AMyActor::OnHit);

UFUNCTION()
void AMyActor::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor,
                      UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit) {}

// Overlap events — SetGenerateOverlapEvents(true) REQUIRED on BOTH components
MyMesh->SetGenerateOverlapEvents(true);
MyMesh->OnComponentBeginOverlap.AddDynamic(this, &AMyActor::OnBeginOverlap);
MyMesh->OnComponentEndOverlap.AddDynamic(this, &AMyActor::OnEndOverlap);

UFUNCTION()
void AMyActor::OnBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor,
    UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) {}

UFUNCTION()
void AMyActor::OnEndOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor,
    UPrimitiveComponent* OtherComp, int32 OtherBodyIndex) {}
Requirements: Hit:
QueryAndPhysics
,
ECR_Block
on both,
SetNotifyRigidBodyCollision(true)
. Overlap:
ECR_Overlap
on both,
SetGenerateOverlapEvents(true)
on both.

来自
PrimitiveComponent.h
的委托声明:
  • OnComponentHit
    (HitComp, OtherActor, OtherComp, NormalImpulse, FHitResult)
    — 物理碰撞触发
  • OnComponentBeginOverlap
    (OverlappedComp, OtherActor, OtherComp, OtherBodyIndex, bFromSweep, SweepResult)
    — 开始重叠触发
  • OnComponentEndOverlap
    (OverlappedComp, OtherActor, OtherComp, OtherBodyIndex)
    — 结束重叠触发
cpp
// 碰撞事件(物理碰撞)
MyMesh->SetNotifyRigidBodyCollision(true);  // 对应编辑器中的“Simulation Generates Hit Events”选项
MyMesh->OnComponentHit.AddDynamic(this, &AMyActor::OnHit);

UFUNCTION()
void AMyActor::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor,
                      UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit) {}

// 重叠事件 — 必须在两个组件上都设置SetGenerateOverlapEvents(true)
MyMesh->SetGenerateOverlapEvents(true);
MyMesh->OnComponentBeginOverlap.AddDynamic(this, &AMyActor::OnBeginOverlap);
MyMesh->OnComponentEndOverlap.AddDynamic(this, &AMyActor::OnEndOverlap);

UFUNCTION()
void AMyActor::OnBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor,
    UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) {}

UFUNCTION()
void AMyActor::OnEndOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor,
    UPrimitiveComponent* OtherComp, int32 OtherBodyIndex) {}
要求:碰撞事件(Hit):需设置为
QueryAndPhysics
、双方响应规则为
ECR_Block
、且启用
SetNotifyRigidBodyCollision(true)
。重叠事件(Overlap):双方响应规则为
ECR_Overlap
、且都启用
SetGenerateOverlapEvents(true)

Physics Bodies

物理刚体

cpp
// Enable simulation (PrimitiveComponent.h / BodyInstanceCore.h)
MyMesh->SetSimulatePhysics(true);
MyMesh->SetEnableGravity(true);
MyMesh->SetMassOverrideInKg(NAME_None, 50.f, true); // 50 kg
MyMesh->SetLinearDamping(0.1f);
MyMesh->SetAngularDamping(0.05f);
float Mass = MyMesh->GetMass();

// Forces and impulses
MyMesh->AddImpulse(FVector(0,0,1000), NAME_None, false);       // bVelChange=true ignores mass
MyMesh->AddImpulseAtLocation(FVector(500,0,0), HitPoint);      // adds torque
MyMesh->AddForce(FVector(0,0,9800), NAME_None, false);          // continuous (per tick)
MyMesh->AddRadialImpulse(Center, 500.f, 2000.f, RIF_Linear, false);
MyMesh->SetPhysicsLinearVelocity(FVector(0,0,300));             // use sparingly
FBodyInstanceCore key flags (set via UPROPERTY/editor):
bSimulatePhysics
,
bOverrideMass
,
bEnableGravity
,
bAutoWeld
,
bStartAwake
,
bGenerateWakeEvents
,
bUpdateKinematicFromSimulation
.
Collision complexity (
BodySetupEnums.h
):
CTF_UseDefault
,
CTF_UseSimpleAndComplex
,
CTF_UseSimpleAsComplex
,
CTF_UseComplexAsSimple
(expensive, static only for physics).
cpp
// 启用模拟(来自PrimitiveComponent.h / BodyInstanceCore.h)
MyMesh->SetSimulatePhysics(true);
MyMesh->SetEnableGravity(true);
MyMesh->SetMassOverrideInKg(NAME_None, 50.f, true); // 设置质量为50千克
MyMesh->SetLinearDamping(0.1f);
MyMesh->SetAngularDamping(0.05f);
float Mass = MyMesh->GetMass();

// 添加力和冲量
MyMesh->AddImpulse(FVector(0,0,1000), NAME_None, false);       // bVelChange=true时忽略质量
MyMesh->AddImpulseAtLocation(FVector(500,0,0), HitPoint);      // 添加冲量并产生扭矩
MyMesh->AddForce(FVector(0,0,9800), NAME_None, false);          // 持续施加力(每帧)
MyMesh->AddRadialImpulse(Center, 500.f, 2000.f, RIF_Linear, false);
MyMesh->SetPhysicsLinearVelocity(FVector(0,0,300));             // 谨慎使用
FBodyInstanceCore关键标志(通过UPROPERTY或编辑器设置):
bSimulatePhysics
bOverrideMass
bEnableGravity
bAutoWeld
bStartAwake
bGenerateWakeEvents
bUpdateKinematicFromSimulation
碰撞复杂度
BodySetupEnums.h
):
CTF_UseDefault
CTF_UseSimpleAndComplex
CTF_UseSimpleAsComplex
CTF_UseComplexAsSimple
(性能开销大,仅静态物体用于物理模拟)。

Physics Constraints

物理约束

cpp
UPhysicsConstraintComponent* C = NewObject<UPhysicsConstraintComponent>(this);
C->SetupAttachment(RootComponent);
C->SetConstrainedComponents(MeshA, NAME_None, MeshB, NAME_None);
C->SetAngularSwing1Limit(EAngularConstraintMotion::ACM_Limited, 45.f);
C->SetAngularTwistLimit(EAngularConstraintMotion::ACM_Free, 0.f);
C->SetLinearXLimit(ELinearConstraintMotion::LCM_Locked, 0.f);
C->RegisterComponent();
Named constraint presets (set via
ConstraintProfile
or editor Preset dropdown):
PresetAngular LimitsLinear Limits
FixedAll lockedAll locked
HingeOne axis freeAll locked
PrismaticAll lockedOne axis free
Ball-and-SocketAll freeAll locked

cpp
UPhysicsConstraintComponent* C = NewObject<UPhysicsConstraintComponent>(this);
C->SetupAttachment(RootComponent);
C->SetConstrainedComponents(MeshA, NAME_None, MeshB, NAME_None);
C->SetAngularSwing1Limit(EAngularConstraintMotion::ACM_Limited, 45.f);
C->SetAngularTwistLimit(EAngularConstraintMotion::ACM_Free, 0.f);
C->SetLinearXLimit(ELinearConstraintMotion::LCM_Locked, 0.f);
C->RegisterComponent();
命名约束预设(通过
ConstraintProfile
或编辑器预设下拉菜单设置):
预设角度限制线性限制
Fixed全部锁定全部锁定
Hinge单轴自由全部锁定
Prismatic全部锁定单轴自由
Ball-and-Socket全部自由全部锁定

Physical Materials (UPhysicalMaterial)

物理材质(UPhysicalMaterial)

From
PhysicalMaterials/PhysicalMaterial.h
:
cpp
float Friction;       // kinetic (0 = frictionless)
float StaticFriction; // before sliding starts
float Restitution;    // 0 (no bounce) to 1 (elastic)
float Density;        // g/cm^3 — used to compute mass from shape volume
EPhysicalSurface SurfaceType; // SurfaceType_Default, SurfaceType1..SurfaceType62
// FrictionCombineMode / RestitutionCombineMode: Average, Min, Multiply, Max

// Runtime override
MyMesh->SetPhysMaterialOverride(MyPhysMaterial);

// Detect surface from trace (requires bReturnPhysicalMaterial=true)
if (UPhysicalMaterial* M = Hit.PhysMaterial.Get())
{
    EPhysicalSurface S = UPhysicalMaterial::DetermineSurfaceType(M);
    switch (S) { case SurfaceType1: /* Metal */ break; }
}

来自
PhysicalMaterials/PhysicalMaterial.h
cpp
float Friction;       // 动摩擦系数(0表示无摩擦)
float StaticFriction; // 静摩擦系数(滑动开始前的摩擦)
float Restitution;    // 弹性系数(0表示无反弹,1表示完全弹性)
float Density;        // 密度(克/立方厘米)—— 根据形状体积计算质量
EPhysicalSurface SurfaceType; // 表面类型:SurfaceType_Default、SurfaceType1..SurfaceType62
// FrictionCombineMode / RestitutionCombineMode:Average(平均)、Min(最小值)、Multiply(相乘)、Max(最大值)

// 运行时覆盖
MyMesh->SetPhysMaterialOverride(MyPhysMaterial);

// 通过轨迹检测表面类型(需要bReturnPhysicalMaterial=true)
if (UPhysicalMaterial* M = Hit.PhysMaterial.Get())
{
    EPhysicalSurface S = UPhysicalMaterial::DetermineSurfaceType(M);
    switch (S) { case SurfaceType1: /* 金属 */ break; }
}

Chaos Physics (UE5)

Chaos物理引擎(UE5)

UE5 uses Chaos by default (PhysX removed). Key architecture:
  • FChaosScene
    (
    ChaosScene.h
    ) owns the solver:
    StartFrame()
    ,
    SetUpForFrame()
    ,
    EndFrame()
    .
  • Physics runs on a dedicated thread; game thread reads results at sync points.
  • Substepping: enabled per Project Settings > Physics (
    MaxSubsteps
    ,
    MaxSubstepDeltaTime
    ). Enable when small/fast objects tunnel through thin geometry — substepping divides the physics tick into smaller increments so collisions are not missed.
  • Async physics: runs simulation on a separate thread with one-frame latency. Enable via
    UPhysicsSettings::bTickPhysicsAsync
    . Use
    UAsyncPhysicsInputComponent
    on components that need physics-thread input callbacks.
Key
UPhysicsSettingsCore
fields (
PhysicsSettingsCore.h
):
cpp
float DefaultGravityZ;         // -980 cm/s^2 default
float BounceThresholdVelocity; // min velocity to bounce
float MaxAngularVelocity;      // rad/s cap
float MaxDepenetrationVelocity;
float ContactOffsetMultiplier; // contact shell size
FChaosSolverConfiguration SolverOptions;
EPhysicalSurface: 62 configurable slots (
SurfaceType1..SurfaceType62
) mapped in Project Settings > Physics > Physical Surface.
Geometry Collections (Chaos Destructibles): use
UGeometryCollectionComponent
. Fracture thresholds driven by
FPhysicalMaterialStrength
(TensileStrength, CompressionStrength, ShearStrength) and
FPhysicalMaterialDamageModifier
(DamageThresholdMultiplier) on
UPhysicalMaterial
.

UE5默认使用Chaos(PhysX已移除)。核心架构:
  • FChaosScene
    ChaosScene.h
    )负责求解器:
    StartFrame()
    SetUpForFrame()
    EndFrame()
  • 物理模拟在专用线程运行;游戏线程在同步点读取结果。
  • 子步模拟:在项目设置>物理中启用(
    MaxSubsteps
    MaxSubstepDeltaTime
    )。当小型/快速物体穿过薄几何体时启用——子步将物理帧拆分为更小的增量,避免遗漏碰撞。
  • 异步物理:在单独线程运行模拟,存在一帧延迟。通过
    UPhysicsSettings::bTickPhysicsAsync
    启用。对需要物理线程输入回调的组件,使用
    UAsyncPhysicsInputComponent
UPhysicsSettingsCore
关键字段(
PhysicsSettingsCore.h
):
cpp
float DefaultGravityZ;         // 默认值为-980厘米/秒²
float BounceThresholdVelocity; // 触发反弹的最小速度
float MaxAngularVelocity;      // 角速度上限(弧度/秒)
float MaxDepenetrationVelocity;
float ContactOffsetMultiplier; // 接触壳大小
FChaosSolverConfiguration SolverOptions;
EPhysicalSurface:62个可配置插槽(
SurfaceType1..SurfaceType62
),在项目设置>物理>物理表面中映射。
几何体集合(Chaos可破坏物体):使用
UGeometryCollectionComponent
。破碎阈值由
UPhysicalMaterial
上的
FPhysicalMaterialStrength
(抗拉强度、抗压强度、剪切强度)和
FPhysicalMaterialDamageModifier
(伤害阈值乘数)驱动。

Cloth Simulation

布料模拟

cpp
// Cloth uses UClothingAssetBase attached to USkeletalMeshComponent
// Enable in Mesh asset: Clothing → Add Clothing Data
// C++ access:
USkeletalMeshComponent* Mesh = GetMesh();
if (UClothingSimulationInteractor* Cloth = Mesh->GetClothingSimulationInteractor())
{
    Cloth->PhysicsAssetUpdated();             // re-sync after physics asset change
    Cloth->SetAnimDriveSpringStiffness(10.f); // blend anim ↔ cloth
}
cpp
// 布料使用附加到USkeletalMeshComponent的UClothingAssetBase
// 在网格体资源中启用:Clothing → Add Clothing Data
// C++访问方式:
USkeletalMeshComponent* Mesh = GetMesh();
if (UClothingSimulationInteractor* Cloth = Mesh->GetClothingSimulationInteractor())
{
    Cloth->PhysicsAssetUpdated();             // 物理资源更改后重新同步
    Cloth->SetAnimDriveSpringStiffness(10.f); // 混合动画与布料模拟
}

Field System

场系统

Field System actors apply forces, strain, and anchors to Chaos destruction and cloth:
cpp
// Place AFieldSystemActor in level, add field nodes:
// URadialFalloff — distance-based falloff
// URadialVector — directional force from center
// UUniformVector — constant directional force
// UBoxFalloff — box-shaped field region

// Trigger destruction at runtime:
AFieldSystemActor* FieldActor = GetWorld()->SpawnActor<AFieldSystemActor>();
URadialFalloff* Falloff = NewObject<URadialFalloff>(FieldActor);
Falloff->SetRadialFalloff(1000000.f, 0.8f, 1.f, 0.f, 500.f, FVector::ZeroVector, EFieldFalloffType::Field_Falloff_Linear);
UFieldSystemMetaDataFilter* Meta = NewObject<UFieldSystemMetaDataFilter>(FieldActor);
Meta->SetMetaDataFilterType(EFieldFilterType::Field_Filter_All, EFieldObjectType::Field_Object_All, EFieldPositionType::Field_Position_CenterOfMass);
FieldActor->GetFieldSystemComponent()->ApplyPhysicsField(true, EFieldPhysicsType::Field_ExternalClusterStrain, Meta, Falloff);

场系统Actor向Chaos破坏物体和布料施加力、应变和锚点:
cpp
// 在关卡中放置AFieldSystemActor,添加场节点:
// URadialFalloff — 基于距离的衰减
// URadialVector — 从中心向外的定向力
// UUniformVector — 恒定定向力
// UBoxFalloff — 盒形场区域

// 在运行时触发破坏:
AFieldSystemActor* FieldActor = GetWorld()->SpawnActor<AFieldSystemActor>();
URadialFalloff* Falloff = NewObject<URadialFalloff>(FieldActor);
Falloff->SetRadialFalloff(1000000.f, 0.8f, 1.f, 0.f, 500.f, FVector::ZeroVector, EFieldFalloffType::Field_Falloff_Linear);
UFieldSystemMetaDataFilter* Meta = NewObject<UFieldSystemMetaDataFilter>(FieldActor);
Meta->SetMetaDataFilterType(EFieldFilterType::Field_Filter_All, EFieldObjectType::Field_Object_All, EFieldPositionType::Field_Position_CenterOfMass);
FieldActor->GetFieldSystemComponent()->ApplyPhysicsField(true, EFieldPhysicsType::Field_ExternalClusterStrain, Meta, Falloff);

Common Mistakes & Anti-Patterns

常见错误与反模式

Wrong collision responses: Overlap events require
ECR_Overlap
AND
bGenerateOverlapEvents=true
on BOTH components.
Traces every Tick on many actors: Use async traces or throttle to 5–10 Hz with a timer.
QueryOnly vs PhysicsOnly confusion:
QueryOnly
= traces only, no physics forces.
PhysicsOnly
= forces only, traces skip it. Use
QueryAndPhysics
for both.
Complex collision in traces:
bTraceComplex=true
is 4–10x more expensive. Default
false
; only enable for precise terrain interaction.
Missing
SetNotifyRigidBodyCollision
:
OnComponentHit
will never fire without it — this flag ("Simulation Generates Hit Events") is separate from collision response.
Sweep vs overlap: Sweep = shape moving along a path (movement, projectile). Overlap = shape at fixed point (AoE, proximity). Don't substitute one for the other.
Physics on dedicated servers: Disable skeletal ragdolls with
bSimulateSkeletalMeshOnDedicatedServer=false
unless server accuracy is required.
错误的碰撞响应规则:重叠事件需要双方都设置
ECR_Overlap
AND
bGenerateOverlapEvents=true
大量Actor每帧执行轨迹查询:使用异步轨迹或通过计时器限制为5–10 Hz。
混淆QueryOnly与PhysicsOnly
QueryOnly
= 仅用于轨迹查询,不处理物理力。
PhysicsOnly
= 仅处理物理力,轨迹查询会忽略它。同时需要两者时使用
QueryAndPhysics
轨迹查询中使用复杂碰撞
bTraceComplex=true
的性能开销是4–10倍。默认使用
false
;仅在需要精确地形交互时启用。
未设置SetNotifyRigidBodyCollision:没有此标志(对应编辑器中的“Simulation Generates Hit Events”),
OnComponentHit
永远不会触发——此标志与碰撞响应规则是分开的。
混淆扫掠与重叠:扫掠 = 形状沿路径移动(移动、 projectile)。重叠 = 形状处于固定点(范围效果、 proximity检测)。不要互相替代。
专用服务器上的物理模拟:除非需要服务器精度,否则通过
bSimulateSkeletalMeshOnDedicatedServer=false
禁用骨骼布娃娃模拟。

Multiplayer & Replicated Actor Collision

多人游戏与复制Actor碰撞

In multiplayer, physics simulation runs on the server. Collision events (
OnComponentHit
,
OnBeginOverlap
) fire on the server only by default — clients do not receive these events unless you replicate them explicitly via RPCs. Clients see physics-simulated actor positions via
FRepMovement
(the replicated transform + velocity struct behind
bReplicateMovement
). Setting
bReplicateMovement = true
on an actor syncs its transform and linear/angular velocity; the underlying physics state itself is not replicated. For client-predicted physics (e.g., projectiles), simulate locally on the client and reconcile with server authority on correction. Cosmetic-only physics — ragdolls, debris, environmental props — can simulate on clients independently without server involvement, since visual fidelity matters more than authority.

在多人游戏中,物理模拟在服务器端运行。默认情况下,碰撞事件(
OnComponentHit
OnBeginOverlap
)仅在服务器端触发——客户端不会收到这些事件,除非通过RPC显式复制。客户端通过
FRepMovement
bReplicateMovement
背后的复制变换+速度结构体)查看物理模拟Actor的位置。在Actor上设置
bReplicateMovement = true
会同步其变换和线/角速度;底层物理状态本身不会被复制。对于客户端预测的物理(如projectile),在客户端本地模拟,并在收到服务器修正时进行协调。仅用于视觉效果的物理——布娃娃、碎片、环境道具——可以在客户端独立模拟,无需服务器参与,因为视觉保真度比权威性更重要。

Required Module Dependencies

必需的模块依赖

csharp
// Build.cs
PublicDependencyModuleNames.AddRange(new string[] {
    "Core", "CoreUObject",
    "Engine",      // UPrimitiveComponent, FHitResult, UWorld trace API
    "PhysicsCore", // UPhysicalMaterial, FCollisionShape, FBodyInstanceCore
});

csharp
// Build.cs
PublicDependencyModuleNames.AddRange(new string[] {
    "Core", "CoreUObject",
    "Engine",      // UPrimitiveComponent、FHitResult、UWorld轨迹API
    "PhysicsCore", // UPhysicalMaterial、FCollisionShape、FBodyInstanceCore
});

Related Skills

关联技能

  • ue-actor-component-architecture
    UPrimitiveComponent
    lifecycle, attachment, registration
  • ue-ai-navigation
    — trace-based sensing and navmesh overlap queries
  • ue-gameplay-abilities
    — targeting systems built on trace and overlap queries
  • ue-cpp-foundations
    — delegate binding syntax and UFUNCTION requirements
  • ue-actor-component-architecture
    UPrimitiveComponent
    生命周期、附加、注册
  • ue-ai-navigation
    — 基于轨迹的感知和导航网格重叠查询
  • ue-gameplay-abilities
    — 基于轨迹和重叠查询构建的瞄准系统
  • ue-cpp-foundations
    — 委托绑定语法和UFUNCTION要求