🎯 目标:
✅ 理解 UE5 交互系统(Interaction System)
✅ 使用 C++ 让玩家拾取物品
✅ 创建交互触发器(Trigger)激活机关
✅ 使用射线检测(Raycast)触发交互
1️⃣ UE5 交互系统概述
在 Unreal Engine 5 中,交互系统允许玩家 拾取物品、开门、触发机关、启动事件 等。常见的交互方式包括:
方式 | 描述 | 适用场景 |
---|---|---|
Overlap(重叠检测) | 进入某个区域时自动触发 | 触发机关、进入房间 |
Raycast(射线检测) | 通过鼠标/键盘瞄准并触发 | 拾取物品、开门、射击 |
按键交互(Key Press) | 按 E 或 F 触发 | NPC 对话、拾取物品 |
今天,我们将实现 拾取物品 和 触发机关,并使用 E 键进行交互!🚀
2️⃣ 创建可拾取物品(PickupItem)
🔹 新建 PickupItem 类
- 在 UE5,点击 “工具” → “新建 C++ 类”
- 选择 Actor 作为基类,命名为 PickupItem
- 点击“创建并添加到项目”,等待 UE5 生成代码
🔹 修改 PickupItem.h
📌 添加 StaticMeshComponent 作为物品的模型,并设置重叠检测
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/StaticMeshComponent.h"
#include "PickupItem.generated.h"
UCLASS()
class MYGAME_API APickupItem : public AActor
{
GENERATED_BODY()
public:
APickupItem();
protected:
virtual void BeginPlay() override;
private:
UPROPERTY(VisibleAnywhere)
UStaticMeshComponent* MeshComponent;
UFUNCTION()
void OnOverlap(AActor* OverlappedActor, AActor* OtherActor);
};
🔹 修改 PickupItem.cpp
📌 初始化 MeshComponent,并绑定 Overlap 事件
#include "PickupItem.h"
#include "GameFramework/Actor.h"
APickupItem::APickupItem()
{
PrimaryActorTick.bCanEverTick = true;
// 创建 StaticMesh 组件
MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent"));
RootComponent = MeshComponent;
static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/Engine/BasicShapes/Cube.Cube"));
if (MeshAsset.Succeeded()) {
MeshComponent->SetStaticMesh(MeshAsset.Object);
}
// 设置为可触发重叠事件
MeshComponent->SetCollisionProfileName(TEXT("OverlapAllDynamic"));
OnActorBeginOverlap.AddDynamic(this, &APickupItem::OnOverlap);
}
void APickupItem::BeginPlay()
{
Super::BeginPlay();
}
void APickupItem::OnOverlap(AActor* OverlappedActor, AActor* OtherActor)
{
if (OtherActor && OtherActor != this)
{
UE_LOG(LogTemp, Warning, TEXT("%s 被 %s 拾取!"), *GetName(), *OtherActor->GetName());
// 销毁物品(模拟拾取)
Destroy();
}
}
✅ 现在,玩家走近 PickupItem,物品会消失并打印拾取信息!
3️⃣ 使用射线检测(Raycast)拾取物品
有时候,我们希望 玩家按 E 键瞄准并拾取物品,可以使用 射线检测(Raycast) 来实现。
📌 修改 PlayerCharacter.h
void Interact();
📌 修改 PlayerCharacter.cpp
void APlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
PlayerInputComponent->BindAction("Interact", IE_Pressed, this, &APlayerCharacter::Interact);
}
void APlayerCharacter::Interact()
{
FVector Start = FirstPersonCamera->GetComponentLocation();
FVector End = Start + (FirstPersonCamera->GetForwardVector() * 500.0f);
FHitResult HitResult;
FCollisionQueryParams CollisionParams;
if (GetWorld()->LineTraceSingleByChannel(HitResult, Start, End, ECC_Visibility, CollisionParams))
{
if (HitResult.GetActor())
{
UE_LOG(LogTemp, Warning, TEXT("拾取物品: %s"), *HitResult.GetActor()->GetName());
// 销毁物品
HitResult.GetActor()->Destroy();
}
}
}
📌 修改 PickupItem.cpp
MeshComponent->SetCollisionProfileName(TEXT("BlockAllDynamic"));
✅ 现在,按 E 键可以瞄准并拾取物品!
4️⃣ 创建触发机关(Trigger Mechanism)
我们将创建一个 TriggerSwitch,当玩家靠近时 打开机关(比如门)。
🔹 新建 TriggerSwitch 类
- 在 UE5,点击 “工具” → “新建 C++ 类”
- 选择 Actor 作为基类,命名为 TriggerSwitch
- 点击“创建并添加到项目”,等待 UE5 生成代码
🔹 修改 TriggerSwitch.h
📌 添加 BoxComponent 作为触发区域
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/BoxComponent.h"
#include "TriggerSwitch.generated.h"
UCLASS()
class MYGAME_API ATriggerSwitch : public AActor
{
GENERATED_BODY()
public:
ATriggerSwitch();
protected:
virtual void BeginPlay() override;
private:
UPROPERTY(VisibleAnywhere)
UBoxComponent* TriggerBox;
UFUNCTION()
void OnOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,UPrimitiveComponent* OtherComp, int32 OtherBodyIndex,bool bFromSweep, const FHitResult& SweepResult);
};
🔹 修改 TriggerSwitch.cpp
📌 初始化触发器,并在玩家进入时触发事件
#include "TriggerSwitch.h"
#include "GameFramework/Actor.h"
ATriggerSwitch::ATriggerSwitch()
{
PrimaryActorTick.bCanEverTick = true;
// 创建 BoxComponent 作为触发区域
TriggerBox = CreateDefaultSubobject<UBoxComponent>(TEXT("TriggerBox"));
RootComponent = TriggerBox;
TriggerBox->SetCollisionProfileName(TEXT("Trigger"));
// 绑定重叠事件
TriggerBox->OnComponentBeginOverlap.AddDynamic(this, &ATriggerSwitch::OnOverlap);
}
void ATriggerSwitch::BeginPlay()
{
Super::BeginPlay();
}
void ATriggerSwitch::OnOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,UPrimitiveComponent* OtherComp, int32 OtherBodyIndex,bool bFromSweep, const FHitResult& SweepResult)
{
if (OtherActor)
{
UE_LOG(LogTemp, Warning, TEXT("触发机关: %s"), *OtherActor->GetName());
}
}
✅ 当玩家进入 TriggerBox 区域,控制台会打印触发信息!
5️⃣ 常见问题 & 解决方案
问题 | 解决方案 |
---|---|
物品不消失 | 确保 Destroy() 被调用 |
E 键无效 | 确保 Interact() 正确绑定到 SetupPlayerInputComponent |
触发器没反应 | BoxComponent 需设置 Trigger 碰撞模式 |
🎯 总结
✅ 实现 Overlap 事件,让物品可拾取
✅ 使用 E 键 + 射线检测拾取物品
✅ 创建 TriggerSwitch 触发机关
✅ 使用 BoxComponent 检测玩家进入区域
🎮 明天我们将学习 AI 交互系统,创建一个智能 NPC! 🚀