UE4/5 与物品交互(Interact)功能实现(c++)

主要有三大部分:角色(Character),物品(Actor)以及接口(Interface)。

首先定义接口

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

#pragma once

#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "Interact.generated.h"

// This class does not need to be modified.
UINTERFACE(MinimalAPI,Blueprintable)
class  UInteract : public UInterface
{
	GENERATED_BODY()
};

/**
 * 
 */
class RPG_API IInteract
{
	GENERATED_BODY()
	// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
	void Interact();
};

这里我定义了一个接口,并有一个BlueprintNativeEvent属性的函数Interact(),用于实现交互功能。

接着给角色添上一个碰撞体(默认物品有自己的碰撞体),注意头文件的包含。

#include "Components/SphereComponent.h"


UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Collsion, meta = (AllowPrivateAccess = "true"))
class USphereComponent* InteractRadius;
InteractRadius= CreateDefaultSubobject<USphereComponent>(TEXT("InteractRadius"));
InteractRadius->SetupAttachment(GetMesh());

之后定义碰撞函数,分为开始碰撞以及结束碰撞。

private:
	//Set collision events
	UFUNCTION()
	void OnInteractBeginOverlap(class UPrimitiveComponent* Component, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
	UFUNCTION()
	void OnInteractEndOverlap(class UPrimitiveComponent* Component, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

要在BeginPlay中绑定碰撞。

void ARPGCharacter::BeginPlay()
{
	// Call the base class  
	Super::BeginPlay();

	//Add Input Mapping Context
	if (APlayerController* PlayerController = Cast<APlayerController>(Controller))
	{
		if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
		{
			Subsystem->AddMappingContext(DefaultMappingContext, 0);
		}
	}

	InteractRadius->OnComponentBeginOverlap.AddDynamic(this,&ARPGCharacter::OnInteractBeginOverlap);
	InteractRadius->OnComponentEndOverlap.AddDynamic(this,&ARPGCharacter::OnInteractEndOverlap);
}

这里实现的是拾取碰撞的第一个物品(注意,角色为碰撞的第一个物品,所以索引从1开始),首先把碰撞到的物品添加到一个TArray<AActor*> InteractableInRange中。

void ARPGCharacter::OnInteractBeginOverlap(class UPrimitiveComponent* Component, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	if (UKismetSystemLibrary::DoesImplementInterface(OtherActor, UInteract::StaticClass()))
	{
		InteractableInRange.AddUnique(OtherActor);
	}
}

void ARPGCharacter::OnInteractEndOverlap(UPrimitiveComponent* Component, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	if (UKismetSystemLibrary::DoesImplementInterface(OtherActor, UInteract::StaticClass()))
	{
		UKismetSystemLibrary::PrintString(this, "error");
		InteractableInRange.Remove(OtherActor);
	}
}

然后在物品基类中继承接口,之后覆写Interact函数(最后一行),PickupItem可以自己在角色类中定义实现自己想要的功能,比如添加进背包等。

UCLASS()
class RPG_API ABasicInteractable : public AActor,public IInteract
{
	GENERATED_BODY()
};
public:
	UFUNCTION(BlueprintCallable)
	virtual void Interact_Implementation() override;
void ABasicInteractable::Interact_Implementation()
{
	Cast<ARPGCharacter>(UGameplayStatics::GetPlayerCharacter(this,0))->PickupItem(ItemInfo);
	this->Destroy();
}

最后按键绑定后(这里自己绑定吧),执行Interact函数。

void ARPGCharacter::Interact()
{
	if (InteractableInRange.Num()>1)
	{
		IInteract::Execute_Interact(InteractableInRange[1]);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值