好的,现在我想把PlayerInteractComponent组件里面的TickInteract函数方法里面的蓝图逻辑迁移到C++;TickInteract函数接着Sequence节点Then0接着判断玩家控制器中拉出来的显示鼠标光标,判断是否为真如果是真的话,获取玩家控制器然后获取鼠标位置的LocationX和LocationY轴连接到从玩家控制器拉出来的将屏幕反向投射到场景节点的ScreenPosition的X和Y上然后将变量里面的LineTraceDist * 将屏幕反向投射到场景节点的worldDirection然后加上world Position的和连接到局部变量TraceEnd;TraceEnd之前还有一个局部变量TraceStart是直接连接到将屏幕反向投射到场景节点的worldPosition中的;如果分支判断走的是False则获取玩家摄像机管理器获取actor位置和获取Actor向前向量,向前向量需要和LineTraceDist相乘的值加上actor位置的值连接到TraceEnd,然后获取到的actor位置的值直接连接到TraceStart中;
接下来就是Then1走的路线是按通道进行线条追踪刚刚创建的局部变量获取到start和end连上,然后将代码中创建好的变量TraceChannel也连上,,接着获取玩家Pawn,创建数组后连接到按通道进行线条追踪节点的Actors to lgonore中bPrintDebugInfo将这个布尔拉出一个选择节点进行判断False是无,true是针对一帧,将选择节点的ReturnValue传入按通道进行线条追踪节点的DrawDebugType中,按通道进行线条追踪lgnoreSelf默认是true,Trace Color是橙色
TraceHitColor是绿色,设置的DrawTime是5.0然后将按通道进行线条追踪节点的OutHit提升成局部变量HitResult类型是命中结果,接着连接到Sequence节点上,和中断命中结果,Sequence节点上的Then0连接到IsValid中并将中断命中结果的HitActor连接到IsValid的InputObject中判断是否存在,然后获取到玩家Pawn将ReturnValue获取到此的距离(GetDistanceTo)节点然后将HitActor连接到GetDistanceTo的目标上,接着做一个判断如果GetDistanceTo输出的值大于PawnInteractDist(默认值是350)则判断分支走True并且set HitResult中;然后这段算是走完了,接着走Then1在拉出一个Sequence,HitResult的命中中断的HitActor,先从Then0开始判断HoveringActor是否存在走IsValid,接着判断HoveringActor与HitActor不相等如果是True走Set Hovering接口,Set Hovering接口有个布尔值bHovering默认是False然后将HoveringActor连到接口的目标上,在进行设置setHoveringActor,如果走了false则直接返回节点(这一大段的意思就是,如果玩家离被击中的物体太远,则视为未击中。如果上一帧拥有不同的悬浮对象,则取消其悬浮。);接着继续判断HitActor是否存在如果存在则走CanInteract接口,接口目标要连上HitActor判断CanInteract接口输出的布尔值Result如果是true走setHoveringActor,HoveringActor连上HitActor,在判断HoveringActor是否存在如果存在则走SetHovering接口,SetHovering目标连上setHoveringActor输出的布尔bHovering是true,接着获取HoverTipWidget变量设置可视性,InVisibility设置为非可命中测试(自身和所有子项),接着连上GetHoverTip接口目标是HoveringActor,输出变量是文本类型HoverTip,将接口输出变量HoverTip拉取出获取文本为空,接着是 选择节点来判断如果是false则直接连上HoverTip如果是真则是交互文本(拿文本为空节点来判断)接着选择节点上的Return Value连上Set Tip Text(是用户控件UW_HoverTip里面的构造函数里面设置了Txt Hover Tip变量,且有个输入文本Text,输入的结果保存在Text的值中且目标是Txt_HoverTip变量),这一段主要的功能是设置新的可交互物体。如果走了False则判断HoverTipWidget是否存在如果存在则HoverTipWidget设置可视性为以折叠然后在保存下来SetHoverActor,这个判断分支也会连在Then1的判断是否存在的IsnotValid中。
注释局部变量HitResult类型是命中结果,TraceStart,TraceEnd的类型都是向量。
接下来我将提供PlayerInteractComponent的.h文件和.cpp文件
.h文件
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "ViewportInteractableInterface.h"
#include "PlayerInteractComponent.generated.h"
class UUserWidget;
class APlayerController;
class UWHoverTipWidget;
class UWidgetBlueprintLibrary;
// 添加交互接口定义
UINTERFACE(MinimalAPI)
class UInteractableInterface : public UInterface
{
GENERATED_BODY()
};
class IInteractableInterface
{
GENERATED_BODY()
public:
// Interact 方法,接收 bPress 参数
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Interactable")
void Interact(bool bPress);
// Investigate 方法,接收 bPress 参数
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Interactable")
void Investigate(bool bPress);
};
// 交互事件委托
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlayerInteracted, AActor*, InteractActor);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlayerInvestigated, AActor*, InvestigatedActor);
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class GARYSCOMBATSYSTEMCPP_API UPlayerInteractComponent : public UActorComponent
{
GENERATED_BODY()
public:
// Called every frame
UPlayerInteractComponent();
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category="Intercat")
float LineTraceDist=2000.0f;
UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category="Intercat")
AActor* HoveringActor=nullptr;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category="Intercat")
bool bEnableInteractTrace=true;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category="Intercat")
bool bPrintDebugInfo=false;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category="Intercat")
TEnumAsByte<ECollisionChannel> TraceChannel=ECC_Visibility;//碰撞通道
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category="UI")
TSubclassOf<UUserWidget> HoverTipWidget;//悬停提示UI
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category="Intercat")
float PawnInteractractDist=350.0f;//交互距离
UPROPERTY(BlueprintAssignable, Category="Intercat")
FOnPlayerInteracted OnBeginPlayEvent;
//蓝图事件绑定,委托
UPROPERTY(BlueprintAssignable, Category="Intercat")
FOnPlayerInteracted OnPlayerInteracted;
UPROPERTY(BlueprintAssignable, Category="Intercat")
FOnPlayerInteracted OnPlayerInvestigated;
protected:
// Called when the game starts
virtual void BeginPlay() override;
private:
UPROPERTY()
UUserWidget* CreatedWidget=nullptr;
UFUNCTION()
void CreateHoverTipUI();
void UpdateHoverUI(AActor* NewHoverActor); // 更新悬停 UI
public:
UFUNCTION(BlueprintCallable)
void TickInteract();
bool PerformLineTrace(FHitResult& OutHitResult); // 执行射线检测
bool IsValidInteractable(AActor* ActorToCheck); // 检查 Actor 是否可交互
// 添加公共方法用于触发交互
UFUNCTION(BlueprintCallable, Category = "Interaction")
void Interact(bool bPress);
UFUNCTION(BlueprintCallable, Category = "Interaction")
void Investigate(bool bPress);
};
.cpp文件
// Fill out your copyright notice in the Description page of Project Settings.
#include "Engine/Engine.h"
#include "Components/PlayerInteractComponent.h"
#include "Engine/World.h"
#include "Blueprint/UserWidget.h"
#include "Engine/CollisionProfile.h"
#include "Kismet/GameplayStatics.h"
#include "Blueprint/WidgetBlueprintLibrary.h"
#include "Components/StaticMeshComponent.h"
#include "Components/WidgetComponent.h"
// Sets default values for this component's properties
UPlayerInteractComponent::UPlayerInteractComponent()
{
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
// off to improve performance if you don't need them.
PrimaryComponentTick.bCanEverTick = true;
// ...
}
// Called when the game starts
void UPlayerInteractComponent::BeginPlay()
{
Super::BeginPlay();
APlayerController*PC=UGameplayStatics::GetPlayerController(GetWorld(), 0);
if (!PC) return;
if (HoverTipWidget)
{
//创建控件实列
CreatedWidget=CreateWidget<UUserWidget>(PC,HoverTipWidget);
if (CreatedWidget)
{
//添加到视口
CreatedWidget->AddToViewport();
//设置初始不可见
CreatedWidget->SetVisibility(ESlateVisibility::Collapsed);
}
}
}
void UPlayerInteractComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
if (bEnableInteractTrace)
{
TickInteract();//执行交互逻辑
//调式信息输出
if (bPrintDebugInfo)
{
FString DebugMessage;
FColor DebugColor=FColor::Green;
if (IsValid(HoveringActor))
{
DebugMessage = FString::Printf(TEXT("Hovering Actor: %s"), *HoveringActor->GetName());
}
else
{
DebugMessage = TEXT("Hovering Actor: None");
}
// 在屏幕上打印调试信息
GEngine->AddOnScreenDebugMessage(-1,0.1,DebugColor,DebugMessage);
}
}
}
void UPlayerInteractComponent::TickInteract()
{
APawn*OwnerPawn=Cast<APawn>(GetOwner());
if (!OwnerPawn) return;
//计算涉嫌起点和终点
FVector Start;
FRotator Rotation;
OwnerPawn->GetController()->GetPlayerViewPoint(Start, Rotation);
FVector End = Start + Rotation.Vector() * 1000.0f;
//射线检测参数
FCollisionQueryParams CollisionParams;
CollisionParams.AddIgnoredActor(GetOwner());
//执行射线检测
FHitResult HitResult;
bool bHit = GetWorld()->LineTraceSingleByChannel(HitResult, Start, End, TraceChannel, CollisionParams);
//更新悬停Actor
HoveringActor = bHit? HitResult.GetActor() : nullptr;
//调试可视化
}
void UPlayerInteractComponent::CreateHoverTipUI()
{
}
bool UPlayerInteractComponent::PerformLineTrace(FHitResult& OutHit)
{
APlayerController* PC = UGameplayStatics::GetPlayerController(GetWorld(), 0);
if (!PC) return false;
FVector Start;
FRotator Rotation;
PC->GetPlayerViewPoint(Start, Rotation);
FVector End = Start + Rotation.Vector() * LineTraceDist;
FCollisionQueryParams Params;
Params.AddIgnoredActor(GetOwner());
return GetWorld()->LineTraceSingleByChannel(OutHit, Start, End, TraceChannel, Params);
}
bool UPlayerInteractComponent::IsValidInteractable(AActor* Actor)
{
if (!Actor) return false;
float Distance = FVector::Dist(GetOwner()->GetActorLocation(), Actor->GetActorLocation());
return Distance <= PawnInteractractDist;
}
void UPlayerInteractComponent::Interact(bool bPress)
{// 检查是否启用交互追踪
if (!bEnableInteractTrace)
{
if (bPrintDebugInfo)
{
UE_LOG(LogTemp, Warning, TEXT("Interact Trace Disabled"));
}
return;
}
// 检查悬停 Actor 是否有效
if (!IsValid(HoveringActor))
{
if (bPrintDebugInfo)
{
UE_LOG(LogTemp, Warning, TEXT("No Valid Hovering Actor to Interact"));
}
return;
}
// 检查 Actor 是否实现了交互接口
if (HoveringActor->Implements<UInteractableInterface>())
{
// 调用接口的 Interact 方法并传递 bPress 参数
IInteractableInterface::Execute_Interact(HoveringActor, bPress);
// 触发交互事件委托
OnPlayerInteracted.Broadcast(HoveringActor);
if (bPrintDebugInfo)
{
UE_LOG(LogTemp, Warning, TEXT("Interacted with Actor: %s (bPress: %s)"),
*HoveringActor->GetName(), bPress ? TEXT("true") : TEXT("false"));
}
}
else
{
if (bPrintDebugInfo)
{
UE_LOG(LogTemp, Warning, TEXT("Actor %s does not implement InteractableInterface"),
*HoveringActor->GetName());
}
}
}
void UPlayerInteractComponent::Investigate(bool bPress)
{
// 检查是否启用交互追踪
if (!bEnableInteractTrace)
{
if (bPrintDebugInfo)
{
UE_LOG(LogTemp, Warning, TEXT("Investigate Trace Disabled"));
}
return;
}
// 检查悬停 Actor 是否有效
if (!IsValid(HoveringActor))
{
if (bPrintDebugInfo)
{
UE_LOG(LogTemp, Warning, TEXT("No Valid Hovering Actor to Investigate"));
}
return;
}
// 检查 Actor 是否实现了交互接口
if (HoveringActor->Implements<UInteractableInterface>())
{
// 调用接口的 Investigate 方法并传递 bPress 参数
IInteractableInterface::Execute_Investigate(HoveringActor, bPress);
// 触发调查事件委托
OnPlayerInvestigated.Broadcast(HoveringActor);
if (bPrintDebugInfo)
{
UE_LOG(LogTemp, Warning, TEXT("Investigated Actor: %s (bPress: %s)"),
*HoveringActor->GetName(), bPress ? TEXT("true") : TEXT("false"));
}
}
else
{
if (bPrintDebugInfo)
{
UE_LOG(LogTemp, Warning, TEXT("Actor %s does not implement InteractableInterface"),
*HoveringActor->GetName());
}
}
}
void UPlayerInteractComponent::UpdateHoverUI(AActor* NewHoverActor)
{
if (NewHoverActor)
{
//显示控件
CreatedWidget->SetVisibility(ESlateVisibility::Visible);
//更新悬停提示内容.....
}
else
{
//隐藏控件
CreatedWidget->SetVisibility(ESlateVisibility::Collapsed);
}
}
最新发布