ue-physics-collision
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseUE 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 to confirm:
.agents/ue-project-context.md- UE version (Chaos is the default physics backend from UE 5.0; PhysX was deprecated)
- Which modules need and
"PhysicsCore"in their"Engine"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:
- Collision setup — channels, profiles, responses on components
- Trace queries — line traces, sweeps, overlap queries for gameplay logic
- Collision events — OnComponentHit, OnBeginOverlap, OnEndOverlap delegates
- Physics simulation — rigid body sim, forces, impulses, damping, constraints
- Physical materials — friction, restitution, surface type detection
若未说明具体场景,请询问用户属于以下哪个领域:
- 碰撞设置 — 组件的通道、配置文件、响应规则
- 轨迹查询 — 用于游戏逻辑的线轨迹、扫掠、重叠查询
- 碰撞事件 — OnComponentHit、OnBeginOverlap、OnEndOverlap委托
- 物理模拟 — 刚体模拟、力、冲量、阻尼、约束
- 物理材质 — 摩擦力、弹性、表面类型检测
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_GameTraceChannel18Responses: / (events, no block) / (physical block + events).
ECR_IgnoreECR_OverlapECR_BlockBuilt-in profiles: , , , , , , .
BlockAllBlockAllDynamicOverlapAllOverlapAllDynamicPawnPhysicsActorNoCollisioncpp
ECC_WorldStatic, ECC_WorldDynamic, ECC_Pawn, ECC_PhysicsBody,
ECC_Vehicle, ECC_Destructible // 对象通道(定义物体的类型)
ECC_Visibility, ECC_Camera // 轨迹通道(用于查询)
// 自定义通道:ECC_GameTraceChannel1..ECC_GameTraceChannel18响应规则:(忽略)/ (重叠,触发事件但不阻挡)/ (物理阻挡+触发事件)。
ECR_IgnoreECR_OverlapECR_Block内置配置文件:、、、、、、。
BlockAllBlockAllDynamicOverlapAllOverlapAllDynamicPawnPhysicsActorNoCollisionSetting 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: matches the target's object type channel; uses the querier's trace channel and checks responses. Most gameplay traces use trace channels (, custom ); overlap queries for "find all pawns" use object type ().
ByObjectTypeByChannelECC_VisibilityWeaponECC_Pawn对象类型通道描述Actor的类型(Pawn、WorldDynamic、Vehicle)。每个组件只能有一个对象类型。轨迹通道用于查询——定义轨迹要检测的目标(Visibility、Camera、Weapon)。这种区别决定了要使用的查询函数:匹配目标的对象类型通道;使用查询者的轨迹通道并检查响应规则。大多数游戏玩法轨迹使用轨迹通道(、自定义通道);“查找所有Pawn”的重叠查询使用对象类型()。
ByObjectTypeByChannelECC_VisibilityWeaponECC_PawnCustom 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=TruebTraceType=FalseSee for full profile examples.
references/collision-channel-setup.mdini
[/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=TruebTraceType=False完整的配置文件示例请查看。
references/collision-channel-setup.mdTrace 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
WorldCollision.hUWorld世界级轨迹函数(C++)—— 来自WorldCollision.h
,通过UWorld
调用
WorldCollision.hUWorldcpp
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
)
CollisionShape.h扫掠查询 — FCollisionShape(来自CollisionShape.h
)
CollisionShape.hcpp
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);
#endifDrawDebugLineDrawDebugSphereDrawDebugHelpers.hENABLE_DRAW_DEBUGbPersistentLinesLifeTimeSee for full gameplay patterns (hitscan, melee sweep, AoE, ground detection, async sensors).
references/trace-patterns.mdcpp
#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);
#endifDrawDebugLineDrawDebugSphereDrawDebugHelpers.hENABLE_DRAW_DEBUGbPersistentLinesLifeTime完整的游戏玩法模式(射线检测、近战扫掠、范围效果、地面检测、异步传感器)请查看。
references/trace-patterns.mdCollision Events
碰撞事件
Delegate declarations from :
PrimitiveComponent.h- —
OnComponentHit— physics collision(HitComp, OtherActor, OtherComp, NormalImpulse, FHitResult) - —
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: , on both, . Overlap: on both, on both.
QueryAndPhysicsECR_BlockSetNotifyRigidBodyCollision(true)ECR_OverlapSetGenerateOverlapEvents(true)来自的委托声明:
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):需设置为、双方响应规则为、且启用。重叠事件(Overlap):双方响应规则为、且都启用。
QueryAndPhysicsECR_BlockSetNotifyRigidBodyCollision(true)ECR_OverlapSetGenerateOverlapEvents(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 sparinglyFBodyInstanceCore key flags (set via UPROPERTY/editor): , , , , , , .
bSimulatePhysicsbOverrideMassbEnableGravitybAutoWeldbStartAwakebGenerateWakeEventsbUpdateKinematicFromSimulationCollision complexity (): , , , (expensive, static only for physics).
BodySetupEnums.hCTF_UseDefaultCTF_UseSimpleAndComplexCTF_UseSimpleAsComplexCTF_UseComplexAsSimplecpp
// 启用模拟(来自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或编辑器设置):、、、、、、。
bSimulatePhysicsbOverrideMassbEnableGravitybAutoWeldbStartAwakebGenerateWakeEventsbUpdateKinematicFromSimulation碰撞复杂度():、、、(性能开销大,仅静态物体用于物理模拟)。
BodySetupEnums.hCTF_UseDefaultCTF_UseSimpleAndComplexCTF_UseSimpleAsComplexCTF_UseComplexAsSimplePhysics 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 or editor Preset dropdown):
ConstraintProfile| Preset | Angular Limits | Linear Limits |
|---|---|---|
| Fixed | All locked | All locked |
| Hinge | One axis free | All locked |
| Prismatic | All locked | One axis free |
| Ball-and-Socket | All free | All 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.hcpp
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.hcpp
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) owns the solver:ChaosScene.h,StartFrame(),SetUpForFrame().EndFrame() - Physics runs on a dedicated thread; game thread reads results at sync points.
- Substepping: enabled per Project Settings > Physics (,
MaxSubsteps). Enable when small/fast objects tunnel through thin geometry — substepping divides the physics tick into smaller increments so collisions are not missed.MaxSubstepDeltaTime - Async physics: runs simulation on a separate thread with one-frame latency. Enable via . Use
UPhysicsSettings::bTickPhysicsAsyncon components that need physics-thread input callbacks.UAsyncPhysicsInputComponent
Key fields ():
UPhysicsSettingsCorePhysicsSettingsCore.hcpp
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 () mapped in Project Settings > Physics > Physical Surface.
SurfaceType1..SurfaceType62Geometry Collections (Chaos Destructibles): use . Fracture thresholds driven by (TensileStrength, CompressionStrength, ShearStrength) and (DamageThresholdMultiplier) on .
UGeometryCollectionComponentFPhysicalMaterialStrengthFPhysicalMaterialDamageModifierUPhysicalMaterialUE5默认使用Chaos(PhysX已移除)。核心架构:
- (
FChaosScene)负责求解器:ChaosScene.h、StartFrame()、SetUpForFrame()。EndFrame() - 物理模拟在专用线程运行;游戏线程在同步点读取结果。
- 子步模拟:在项目设置>物理中启用(、
MaxSubsteps)。当小型/快速物体穿过薄几何体时启用——子步将物理帧拆分为更小的增量,避免遗漏碰撞。MaxSubstepDeltaTime - 异步物理:在单独线程运行模拟,存在一帧延迟。通过启用。对需要物理线程输入回调的组件,使用
UPhysicsSettings::bTickPhysicsAsync。UAsyncPhysicsInputComponent
UPhysicsSettingsCorePhysicsSettingsCore.hcpp
float DefaultGravityZ; // 默认值为-980厘米/秒²
float BounceThresholdVelocity; // 触发反弹的最小速度
float MaxAngularVelocity; // 角速度上限(弧度/秒)
float MaxDepenetrationVelocity;
float ContactOffsetMultiplier; // 接触壳大小
FChaosSolverConfiguration SolverOptions;EPhysicalSurface:62个可配置插槽(),在项目设置>物理>物理表面中映射。
SurfaceType1..SurfaceType62几何体集合(Chaos可破坏物体):使用。破碎阈值由上的(抗拉强度、抗压强度、剪切强度)和(伤害阈值乘数)驱动。
UGeometryCollectionComponentUPhysicalMaterialFPhysicalMaterialStrengthFPhysicalMaterialDamageModifierCloth 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 AND on BOTH components.
ECR_OverlapbGenerateOverlapEvents=trueTraces every Tick on many actors: Use async traces or throttle to 5–10 Hz with a timer.
QueryOnly vs PhysicsOnly confusion: = traces only, no physics forces. = forces only, traces skip it. Use for both.
QueryOnlyPhysicsOnlyQueryAndPhysicsComplex collision in traces: is 4–10x more expensive. Default ; only enable for precise terrain interaction.
bTraceComplex=truefalseMissing : will never fire without it — this flag ("Simulation Generates Hit Events") is separate from collision response.
SetNotifyRigidBodyCollisionOnComponentHitSweep 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 unless server accuracy is required.
bSimulateSkeletalMeshOnDedicatedServer=false错误的碰撞响应规则:重叠事件需要双方都设置 AND 。
ECR_OverlapbGenerateOverlapEvents=true大量Actor每帧执行轨迹查询:使用异步轨迹或通过计时器限制为5–10 Hz。
混淆QueryOnly与PhysicsOnly: = 仅用于轨迹查询,不处理物理力。 = 仅处理物理力,轨迹查询会忽略它。同时需要两者时使用。
QueryOnlyPhysicsOnlyQueryAndPhysics轨迹查询中使用复杂碰撞:的性能开销是4–10倍。默认使用;仅在需要精确地形交互时启用。
bTraceComplex=truefalse未设置SetNotifyRigidBodyCollision:没有此标志(对应编辑器中的“Simulation Generates Hit Events”),永远不会触发——此标志与碰撞响应规则是分开的。
OnComponentHit混淆扫掠与重叠:扫掠 = 形状沿路径移动(移动、 projectile)。重叠 = 形状处于固定点(范围效果、 proximity检测)。不要互相替代。
专用服务器上的物理模拟:除非需要服务器精度,否则通过禁用骨骼布娃娃模拟。
bSimulateSkeletalMeshOnDedicatedServer=falseMultiplayer & Replicated Actor Collision
多人游戏与复制Actor碰撞
In multiplayer, physics simulation runs on the server. Collision events (, ) 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 (the replicated transform + velocity struct behind ). Setting 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.
OnComponentHitOnBeginOverlapFRepMovementbReplicateMovementbReplicateMovement = true在多人游戏中,物理模拟在服务器端运行。默认情况下,碰撞事件(、)仅在服务器端触发——客户端不会收到这些事件,除非通过RPC显式复制。客户端通过(背后的复制变换+速度结构体)查看物理模拟Actor的位置。在Actor上设置会同步其变换和线/角速度;底层物理状态本身不会被复制。对于客户端预测的物理(如projectile),在客户端本地模拟,并在收到服务器修正时进行协调。仅用于视觉效果的物理——布娃娃、碎片、环境道具——可以在客户端独立模拟,无需服务器参与,因为视觉保真度比权威性更重要。
OnComponentHitOnBeginOverlapFRepMovementbReplicateMovementbReplicateMovement = trueRequired 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-architecturelifecycle, attachment, registrationUPrimitiveComponent - — trace-based sensing and navmesh overlap queries
ue-ai-navigation - — targeting systems built on trace and overlap queries
ue-gameplay-abilities - — delegate binding syntax and UFUNCTION requirements
ue-cpp-foundations
- —
ue-actor-component-architecture生命周期、附加、注册UPrimitiveComponent - — 基于轨迹的感知和导航网格重叠查询
ue-ai-navigation - — 基于轨迹和重叠查询构建的瞄准系统
ue-gameplay-abilities - — 委托绑定语法和UFUNCTION要求
ue-cpp-foundations