UE5 C++(十一)— 碰撞检测

代理绑定BeginOverlap和EndOverlap

首先,创建自定义ActorC++类 MyCustomActor
添加碰撞组件

#include "Components/BoxComponent.h"

public:
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "MyScene")
	class UBoxComponent *MyBoxComponent;
AMyCustomActor::AMyCustomActor()
{
	PrimaryActorTick.bCanEverTick = true;
	// 创建组件
	MySceneComponent = CreateDefaultSubobject<USceneComponent>(TEXT("CustomScene"));
	MyMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("CustomStaticMesh"));
	MyBoxComponent = CreateDefaultSubobject<UBoxComponent>(TEXT("CustomBox"));
}

动态绑定BeginOverlap和EndOverlap

public:
	//声明绑定函数
	UFUNCTION()
	void BeginOverlapFunction(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult);
	UFUNCTION()
	void EndOverlapFunction(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex);
// Called when the game starts or when spawned
void AMyCustomActor::BeginPlay()
{
	Super::BeginPlay();

	MyBoxComponent->OnComponentBeginOverlap.AddDynamic(this, &AMyCustomActor::BeginOverlapFunction);
	MyBoxComponent->OnComponentEndOverlap.AddDynamic(this, &AMyCustomActor::EndOverlapFunction);
}

void AMyCustomActor::BeginOverlapFunction(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult)
{
	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("BeginOverlapFunction !!")));
}
void AMyCustomActor::EndOverlapFunction(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex)
{
	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("EndOverlapFunction !!")));
}

编译脚本之后

在这里插入图片描述

创建刚才脚本的蓝图类 BP_MyCustomActor 并放到场景中

在这里插入图片描述
调整碰撞区域大小
在这里插入图片描述
然后,添加第三人称人物,并拖拽到场景中
在这里插入图片描述
在这里插入图片描述
运行之后,碰到和离开都会打印日志
在这里插入图片描述
完整的MyCustomActor脚本
MyCustomActor.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
// 引入组件
#include "Components/SceneComponent.h"
#include "Components/StaticMeshComponent.h"
#include "Components/BoxComponent.h"
#include "Components/AudioComponent.h"
#include "Particles/ParticleSystemComponent.h"
#include "GameFramework/Actor.h"
#include "MyCustomActor.generated.h"

UCLASS()
class DEMO_API AMyCustomActor : public AActor
{
	GENERATED_BODY()

public:
	// Sets default values for this actor's properties
	AMyCustomActor();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	// 自定义组件
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "MyScene")
	class USceneComponent *MySceneComponent;
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "MyScene")
	class UStaticMeshComponent *MyMeshComponent;
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "MyScene")
	class UBoxComponent *MyBoxComponent;
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "MyScene")
	class UAudioComponent *MyAudioComponent;
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "MyScene")
	class UParticleSystemComponent *MyParticleSystemComponent;

	//声明绑定函数
	UFUNCTION()
	void BeginOverlapFunction(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult);
	UFUNCTION()
	void EndOverlapFunction(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex);
};

MyCustomActor.cpp


#include "MyCustomActor.h"

// Sets default values
AMyCustomActor::AMyCustomActor()
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	// 创建组件
	MySceneComponent = CreateDefaultSubobject<USceneComponent>(TEXT("CustomScene"));
	MyMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("CustomStaticMesh"));
	MyBoxComponent = CreateDefaultSubobject<UBoxComponent>(TEXT("CustomBox"));
	MyAudioComponent = CreateDefaultSubobject<UAudioComponent>(TEXT("CustomAudio"));
	MyParticleSystemComponent = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("CustomParticleSystem"));

	// 把组件添加到根组件
	RootComponent = MySceneComponent;
	MyMeshComponent->SetupAttachment(MySceneComponent);
	MyBoxComponent->SetupAttachment(MySceneComponent);
	MyAudioComponent->SetupAttachment(MyBoxComponent);
	MyParticleSystemComponent->SetupAttachment(MySceneComponent);
}

// Called when the game starts or when spawned
void AMyCustomActor::BeginPlay()
{
	Super::BeginPlay();

	MyBoxComponent->OnComponentBeginOverlap.AddDynamic(this, &AMyCustomActor::BeginOverlapFunction);
	MyBoxComponent->OnComponentEndOverlap.AddDynamic(this, &AMyCustomActor::EndOverlapFunction);
}

// Called every frame
void AMyCustomActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}
void AMyCustomActor::BeginOverlapFunction(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult)
{
	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("BeginOverlapFunction !!")));
}
void AMyCustomActor::EndOverlapFunction(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex)
{
	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("EndOverlapFunction !!")));
}

Hit事件的代理绑定

以上面同样的方式创建Hit的绑定实现

UFUNCTION()
	void HitFunction(UPrimitiveComponent *HitComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, FVector NormalImpulse, const FHitResult &Hit);
void AMyCustomActor::BeginPlay()
{
	Super::BeginPlay();
	MyBoxComponent->OnComponentHit.AddDynamic(this, &AMyCustomActor::HitFunction);
}
void AMyCustomActor::HitFunction(UPrimitiveComponent *HitComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, FVector NormalImpulse, const FHitResult &Hit)
{
	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("HitFunction !!")));
}

不同的是修改碰撞设置
这个是绑定BeginOverlap和EndOverlap
在这里插入图片描述

这个是Hit事件的代理绑定
在这里插入图片描述
Hit事件的代理绑定之后运行 ,当人物尝试一直前进碰到锥体时会一直触发事件
不像BeginOverlap和EndOverlap只会触发一次

在这里插入图片描述

碰撞设置

官网上有相关参考文档
为静态网格体设置碰撞体积
组件和碰撞
在这里插入图片描述
在C++脚本中设置

// Sets default values
AMyCustomActor::AMyCustomActor()
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	// 创建组件
	MySceneComponent = CreateDefaultSubobject<USceneComponent>(TEXT("CustomScene"));
	MyMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("CustomStaticMesh"));
	MyBoxComponent = CreateDefaultSubobject<UBoxComponent>(TEXT("CustomBox"));
	MyAudioComponent = CreateDefaultSubobject<UAudioComponent>(TEXT("CustomAudio"));
	MyParticleSystemComponent = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("CustomParticleSystem"));

	// 把组件添加到根组件
	RootComponent = MySceneComponent;
	MyMeshComponent->SetupAttachment(MySceneComponent);
	MyBoxComponent->SetupAttachment(MySceneComponent);
	MyAudioComponent->SetupAttachment(MyBoxComponent);
	MyParticleSystemComponent->SetupAttachment(MySceneComponent);

/****************************** 设置碰撞 ****************************************/

	//碰撞设置
	MyBoxComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
	MyBoxComponent->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
	MyBoxComponent->SetCollisionEnabled(ECollisionEnabled::PhysicsOnly);
	MyBoxComponent->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
	MyBoxComponent->SetCollisionEnabled(ECollisionEnabled::ProbeOnly);
	MyBoxComponent->SetCollisionEnabled(ECollisionEnabled::QueryAndProbe);
	//碰撞对象类型
	MyBoxComponent->SetCollisionObjectType(ECC_WorldStatic);
	MyBoxComponent->SetCollisionObjectType(ECC_WorldDynamic);
	MyBoxComponent->SetCollisionObjectType(ECC_Pawn);
	MyBoxComponent->SetCollisionObjectType(ECC_PhysicsBody);
	MyBoxComponent->SetCollisionObjectType(ECC_Vehicle);
	MyBoxComponent->SetCollisionObjectType(ECC_Destructible);
	//碰撞响应
	MyBoxComponent->SetCollisionResponseToAllChannels(ECR_Block);//对所有通道进行设置,响应为Block,阻挡
	MyBoxComponent->SetCollisionResponseToAllChannels(ECR_Overlap);//对所有通道进行设置,响应为Overlap,重叠
	MyBoxComponent->SetCollisionResponseToAllChannels(ECR_Ignore);//忽略
	MyBoxComponent->SetCollisionResponseToChannel(ECC_Pawn,ECR_Overlap);//对单个通道进行响应
	MyBoxComponent->SetCollisionResponseToChannel(ECC_WorldStatic,ECR_Block);//对单个通道进行响应
	MyBoxComponent->SetCollisionResponseToChannel(ECC_WorldDynamic,ECR_Ignore);//对单个通道进行响应

}
### UE5碰撞检测函数使用教程 #### 获取并设置碰撞组件 为了实现有效的碰撞检测,在虚幻引擎5 (UE5) 中,通常会先获取装备的武器中的碰撞组件。这可以通过调用特定于Actor蓝图类的方法来完成,该方法返回关联的`UShapeComponent`或其他类型的碰撞组件[^1]。 ```cpp // C++ 示例:获取武器上的碰撞组件 UShapeComponent* WeaponCollisionComp = Cast<UShapeComponent>(WeaponActor->GetComponentByClass(UShapeComponent::StaticClass())); if (WeaponCollisionComp != nullptr) { // 对获得的碰撞组件执行操作... } ``` #### 执行射线追踪查询 对于更复杂的交互需求,如射击游戏中的命中判定,则可以利用`LineTraceSingleByChannel`或`LineTraceSingleByObjectType`来进行精确的位置探测。这些功能允许开发者指定起点和终点,并沿直线路径测试是否存在障碍物[^2]。 ```cpp FHitResult Hit; FCollisionQueryParams TraceParams(FName(TEXT("")), false, GetOwner()); bool bHit = GetWorld()->LineTraceSingleByChannel( Hit, StartLocation, EndLocation, ECollisionChannel::ECC_Visibility, TraceParams); if(bHit){ // 处理击中目标后的逻辑... } ``` #### 注册事件响应 为了让物体能够感知周围环境的变化,还可以注册各种形式的事件监听器,比如当发生重叠(`OnComponentBeginOverlap`)或是结束接触(`OnComponentEndOverlap`)时触发相应的回调处理程序。 ```cpp // 动态绑定事件处理器至碰撞组件上 WeaponCollisionComp->OnComponentBeginOverlap.AddDynamic(this,&AYourCharacter::HandleBeginOverlap); void AYourCharacter::HandleBeginOverlap(UPrimitiveComponent* OverlappedComponent,AActor* OtherActor, UPrimitiveComponent* OtherComp,int32 OtherBodyIndex,bool bFromSweep,const FHitResult& SweepResult){ // 实现具体业务逻辑... } ``` 通过上述方式可以在UE5项目内构建起一套完整的物理反馈机制,不仅限于简单的触碰反应,还包括基于视线、声音传播等多种维度的空间关系判断。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值