Trace Channel与Object Channel
Trace Channel默认包含Visibility和Camera
是针对全局的,因为每个物体都会包含Visibility属性,和对Camera的反应;
Object Channel默认包含WorldStatic/WorldDynamic/Pawn/PhysicsBody[物理躯体,开启物理模拟会自动选择为它]/Destructible[可破坏物]
Line Trace
从起点到终点生成一条射线,检测上线的所有碰撞,返回符合条件的检测目标;
Line Trace返回的第一个符合条件的;
Multi Line Trace 返回的是所有符合条件的;
Trace For Objects的输入是一个数组:表示可以检测多个不同的对象类型Object Types;
Trace by Channel只有一个输入:表示只能检测一个通道;
具体并无本质区别,不要纠结这个,如果非要说怎么样:
我们可以认为Trace Channel是叠加在Object Channel上面的,每个Object Channel可以同时拥有Visibility属性,而Object Channel本身不能叠加,只能代表自己的类型;
所以默认Trace Channel更广泛;
但实际使用上,你加入加入了自己的Trace Channel:MyChannel,然后你用Line Trace By Channel去检测,行不行,当然是可行的;你说MyChannel不是一个广泛的属性,这不重要;
OnComponentBeginOverlap 参数解析
OnComponentBeginOverlap
是 Unreal Engine 中一个非常重要的碰撞事件,当一个组件开始与另一个组件重叠时触发。以下是该事件的详细参数解析:
函数签名
void OnComponentBeginOverlap(
UPrimitiveComponent* OverlappedComponent,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult
)
参数详解
-
OverlappedComponent (
UPrimitiveComponent*
)- 当前组件,即触发重叠事件的组件
- 通常用于确定是哪个碰撞体触发了事件(如果你有多个碰撞体时)
-
OtherActor (
AActor*
)- 与之发生重叠的另一个Actor
- 这是重叠对象的顶层Actor,可以通过它获取对方的各种组件和属性
-
OtherComp (
UPrimitiveComponent*
)- 与之发生重叠的另一个组件的具体碰撞体
- 如果对方Actor有多个碰撞体,这个参数可以告诉你具体是哪个碰撞体触发了重叠
-
OtherBodyIndex (
int32
)- 主要用于骨骼网格体(Skeletal Mesh),表示碰撞的具体物理体索引
- 对于静态网格体(Static Mesh)通常为0
-
bFromSweep (
bool
)- 表示重叠是否由扫描(Sweep)移动引起
- 如果为true,表示是移动过程中检测到的重叠
- 如果为false,表示是静态检测到的重叠
-
SweepResult (
const FHitResult&
)- 只有当bFromSweep为true时才有意义
- 包含扫描移动碰撞的详细信息,如碰撞点、法线、距离等
注意事项
-
确保组件已启用重叠检测:
- 在组件属性中设置
Generate Overlap Events
为 true - 设置正确的碰撞预设(Collision Preset)或自定义碰撞响应
- 在组件属性中设置
-
绑定事件通常在
BeginPlay
中完成:MyCollisionComponent->OnComponentBeginOverlap.AddDynamic(this, &AMyActor::OnComponentBeginOverlap);
-
性能考虑:频繁的重叠事件可能影响性能,应合理使用
-
区分
Overlap
和Collision
:- Overlap是重叠检测,物体可以相互穿透
- Collision是碰撞检测,物体会被阻挡
理解这些参数对于正确处理游戏中的物理交互非常重要,特别是在制作角色移动、触发器、伤害区域等功能时。
扫描(Sweep)移动
在 Unreal Engine 中,“重叠是否由扫描(Sweep)移动引起” 这个参数 (bFromSweep
) 表示当前的重叠事件是否是由于某个物体通过带扫描的移动(Sweep Movement)而触发的。
1. 什么是 Sweep 移动?
Sweep(扫描)移动是一种带碰撞检测的移动方式。当物体移动时,引擎会沿着移动路径检查是否会与其他物体发生碰撞或重叠,而不是直接"瞬移"到目标位置。
-
Sweep 移动(
bSweep=true
):- 物体会检查移动路径上的所有障碍
- 如果碰到障碍,可能会停止移动或触发重叠/碰撞事件
- 适用于物理模拟、角色移动、抛射物等需要精确碰撞检测的情况
-
非 Sweep 移动(
bSweep=false
):- 物体直接"传送"到目标位置,不检查路径
- 可能直接穿透其他物体,但后续仍然可能触发重叠事件(如果已经重叠)
- 适用于瞬移、非物理对象移动等场景
2. bFromSweep
参数的含义
在 OnComponentBeginOverlap
事件中,bFromSweep
参数告诉你:
true
:这次重叠是因为某个物体正在移动(使用了 Sweep 移动),并在移动过程中检测到了重叠。false
:这次重叠是静态检测到的,比如两个物体本来就重叠,或者其中一个物体直接"传送"到了另一个物体内部(非 Sweep 移动)。
3. 实际应用示例
情况 1:角色移动(Sweep 移动)
// 角色移动时通常会使用 Sweep 移动
void AMyCharacter::MoveForward(float Value)
{
FVector Direction = GetActorForwardVector();
AddMovementInput(Direction, Value); // 内部使用 Sweep 移动
}
- 如果角色撞到另一个物体,
OnComponentBeginOverlap
会被调用,且bFromSweep=true
。 - 你可以通过
SweepResult
获取碰撞点、法线等信息。
情况 2:直接设置位置(非 Sweep 移动)
// 直接设置位置(非 Sweep 移动)
void AMyActor::TeleportTo(FVector NewLocation)
{
SetActorLocation(NewLocation, false); // bSweep=false
}
- 如果新位置与其他物体重叠,
OnComponentBeginOverlap
会被调用,但bFromSweep=false
。 SweepResult
可能不包含有效数据(因为不是扫描移动)。
4. 如何判断是否该使用 bFromSweep
?
-
bFromSweep=true
:- 适用于动态移动(如角色、抛射物、物理模拟物体)
- 可以获取
SweepResult
数据(如碰撞点、法线) - 可以用来实现子弹命中检测、角色撞击效果等
-
bFromSweep=false
:- 适用于静态重叠(如触发器、传送门、区域伤害)
- 通常不需要
SweepResult
数据 - 可以用来检测玩家是否进入某个区域
5. 总结
参数 | 含义 | 适用场景 |
---|---|---|
bFromSweep=true | 重叠由 Sweep 移动引起 | 动态移动(角色、子弹、物理模拟) |
bFromSweep=false | 重叠是静态检测到的 | 触发器、传送、直接设置位置 |
理解 bFromSweep
可以帮助你更精确地处理碰撞和重叠事件,特别是在需要区分动态碰撞和静态重叠的情况下。
Sweep一直是false
如果你的 OnComponentBeginOverlap
事件中的 bFromSweep
参数一直是 false
,说明你的物体移动方式没有使用 Sweep(扫描)检测。要让 bFromSweep
变为 true
,你需要确保物体的移动方式启用了 Sweep 检测。
1. 如何让 bFromSweep
变为 true
?
方法 1:使用 MoveComponent
或 AddMovementInput
(带 Sweep)
如果你的物体是 Actor
或 Character
,确保移动时启用 Sweep:
// 方式 1:使用 SetActorLocation 并启用 Sweep
SetActorLocation(NewLocation, true); // 第二个参数 bSweep=true
// 方式 2:使用 CharacterMovement(适用于角色)
GetCharacterMovement()->MoveUpdatedComponent(Delta, NewRotation, true); // bSweep=true
// 方式 3:使用 UPrimitiveComponent 的移动
MyMeshComponent->MoveComponent(Delta, NewRotation, true); // bSweep=true
方法 2:使用 ProjectileMovementComponent
(抛射物)
如果你的物体是子弹或抛射物,ProjectileMovementComponent
默认启用 Sweep:
UProjectileMovementComponent* Projectile = GetProjectileMovement();
Projectile->SetVelocityInLocalSpace(FVector::ForwardVector * 1000.f);
// 默认 bShouldBounce=true 也会触发 Sweep
方法 3:手动调用 Sweep
检测
如果你想手动检测 Sweep,可以使用 UKismetSystemLibrary::BoxSweep
、SphereSweep
等:
TArray<FHitResult> Hits;
bool bHit = UKismetSystemLibrary::SphereSweepMulti(
GetWorld(),
StartLocation,
EndLocation,
Radius,
TraceChannel,
false, // bTraceComplex
ActorsToIgnore,
EDrawDebugTrace::ForDuration,
Hits,
true // bIgnoreSelf
);
if (bHit)
{
// 处理 Sweep 检测结果
}
2. 常见问题:为什么 bFromSweep
仍然是 false
?
问题 1:直接 SetActorLocation
但没有启用 Sweep
SetActorLocation(NewLocation); // 默认 bSweep=false
✅ 修复:
SetActorLocation(NewLocation, true); // 启用 Sweep
问题 2:使用 TeleportTo
或 SetActorTransform
但未启用 Sweep
TeleportTo(NewLocation); // 默认不启用 Sweep
SetActorTransform(NewTransform); // 默认 bSweep=false
✅ 修复:
TeleportTo(NewLocation, false, true); // 启用 Sweep
SetActorTransform(NewTransform, true); // 启用 Sweep
问题 3:物理模拟(Physics)可能不触发 Sweep
如果你的物体是物理模拟(Simulate Physics
),移动可能由 PhysX 引擎处理,不一定触发 Sweep 事件。
✅ 修复:
- 改用
AddForce
或AddImpulse
,并监听OnComponentHit
而非OnComponentBeginOverlap
。
3. 如何验证 Sweep 是否生效?
方式 1:打印 bFromSweep
void AMyActor::OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
UE_LOG(LogTemp, Warning, TEXT("bFromSweep: %d"), bFromSweep);
if (bFromSweep)
{
UE_LOG(LogTemp, Warning, TEXT("Hit Location: %s"), *SweepResult.ImpactPoint.ToString());
}
}
方式 2:调试绘制 Sweep 路径
// 在移动前绘制调试线
DrawDebugLine(GetWorld(), StartLocation, EndLocation, FColor::Green, false, 2.0f, 0, 1.0f);
4. 总结
方法 | 适用情况 | 代码示例 |
---|---|---|
SetActorLocation + Sweep | 普通 Actor 移动 | SetActorLocation(NewPos, true) |
CharacterMovement | 角色移动 | GetCharacterMovement()->MoveUpdatedComponent(Delta, Rotation, true) |
ProjectileMovement | 子弹/抛射物 | 默认启用 Sweep |
手动 Sweep 检测 | 自定义碰撞检测 | UKismetSystemLibrary::SphereSweepMulti |
如果你的 bFromSweep
仍然是 false
,检查:
- 是否使用了正确的移动方式(
SetActorLocation
要传bSweep=true
)。 - 是否物理模拟影响了碰撞检测(改用
OnComponentHit
)。 - 是否重叠是由静态物体引起(如直接生成在另一个物体内部)。
这样就能确保 bFromSweep
在需要时变为 true
! 🚀