UE4中对TArray<AActor*>数组按对象空间高度排序

// 注意,不可在异步线程中使用。
void SortActorHeight(TArray<AActor*>& ActorList)
{
	// 转存到 SortList。
	TArray<uint64> SortList;
	for (int32 i = 0; i < ActorList.Num(); i++)
	{
		if (ActorList[i] != NULL)
		{
			SortList.Add((uint64)ActorList[i]);
		}
	}

	// 执行排序:
	{
		SortList.Sort([](uint64 A, uint64 B) {
			AActor* pA = (AActor*)A;
			AActor* pB = (AActor*)B;
			if (pA && pB)
			{
				return (pA->GetActorLocation().Z <= pB->GetActorLocation().Z);
			}
			return true;
			});
	}

	// 转存到新数组:
	ActorList.Empty();
	for (int32 t = 0; t < SortList.Num(); t++)
	{
		ActorList.Add((AActor*)SortList[t]);
	}
}

好的,现在我想把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); } }
最新发布
07-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值