UE_基础_碰撞/重叠

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
)

参数详解

  1. OverlappedComponent (UPrimitiveComponent*)

    • 当前组件,即触发重叠事件的组件
    • 通常用于确定是哪个碰撞体触发了事件(如果你有多个碰撞体时)
  2. OtherActor (AActor*)

    • 与之发生重叠的另一个Actor
    • 这是重叠对象的顶层Actor,可以通过它获取对方的各种组件和属性
  3. OtherComp (UPrimitiveComponent*)

    • 与之发生重叠的另一个组件的具体碰撞体
    • 如果对方Actor有多个碰撞体,这个参数可以告诉你具体是哪个碰撞体触发了重叠
  4. OtherBodyIndex (int32)

    • 主要用于骨骼网格体(Skeletal Mesh),表示碰撞的具体物理体索引
    • 对于静态网格体(Static Mesh)通常为0
  5. bFromSweep (bool)

    • 表示重叠是否由扫描(Sweep)移动引起
    • 如果为true,表示是移动过程中检测到的重叠
    • 如果为false,表示是静态检测到的重叠
  6. SweepResult (const FHitResult&)

    • 只有当bFromSweep为true时才有意义
    • 包含扫描移动碰撞的详细信息,如碰撞点、法线、距离等

注意事项

  1. 确保组件已启用重叠检测:

    • 在组件属性中设置 Generate Overlap Events 为 true
    • 设置正确的碰撞预设(Collision Preset)或自定义碰撞响应
  2. 绑定事件通常在 BeginPlay 中完成:

    MyCollisionComponent->OnComponentBeginOverlap.AddDynamic(this, &AMyActor::OnComponentBeginOverlap);
    
  3. 性能考虑:频繁的重叠事件可能影响性能,应合理使用

  4. 区分 OverlapCollision

    • 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:使用 MoveComponentAddMovementInput(带 Sweep)

如果你的物体是 ActorCharacter,确保移动时启用 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::BoxSweepSphereSweep 等:

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:使用 TeleportToSetActorTransform 但未启用 Sweep

TeleportTo(NewLocation); // 默认不启用 Sweep
SetActorTransform(NewTransform); // 默认 bSweep=false

修复

TeleportTo(NewLocation, false, true); // 启用 Sweep
SetActorTransform(NewTransform, true); // 启用 Sweep

问题 3:物理模拟(Physics)可能不触发 Sweep

如果你的物体是物理模拟(Simulate Physics,移动可能由 PhysX 引擎处理,不一定触发 Sweep 事件。
修复

  • 改用 AddForceAddImpulse,并监听 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,检查:

  1. 是否使用了正确的移动方式SetActorLocation 要传 bSweep=true)。
  2. 是否物理模拟影响了碰撞检测(改用 OnComponentHit)。
  3. 是否重叠是由静态物体引起(如直接生成在另一个物体内部)。

这样就能确保 bFromSweep 在需要时变为 true! 🚀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值