当前位置: 首页 > news >正文

虚幻引擎5 GAS开发俯视角RPG游戏 P07-11 实现自动运行

目标:当鼠标左键短暂的按一下地面,角色可以自动的移动到点击位置.

1.在CC_PlayerController.cpp里的AbilityInputTagReleased()函数里:

(1)判断是不是鼠标左键,不是鼠标左键执行技能操作:

/*如果不是鼠标左键*/if (!InputTag.MatchesTagExact(CC_GameplayTags::Input_LMB)){if (GetCC_AbilitySystemComponent() == nullptr) return;GetCC_AbilitySystemComponent()->AbilityInputTagReleased(InputTag);return;}

(2)判断点击地点是不是敌人类,如果是敌人类,执行技能:

/*如果是鼠标左键*/if (bTargetting)	//是敌人类{if (GetCC_AbilitySystemComponent() == nullptr) return;GetCC_AbilitySystemComponent()->AbilityInputTagReleased(InputTag);return;}

(3)判断是不是长按,如果是长按,就退出:

if(FollowTime > ShortPressThreshold)	return;		//长按,退出

(4)角色不存在,就退出:

APawn* ControlledPawn = GetPawn<APawn>();if (ControlledPawn == nullptr) return;

(5)找到路径

a. 构建文件,添加导航系统模块:

Source/CC_Aura/CC_Aura.Build.cs:

PrivateDependencyModuleNames.AddRange(new string[] { "GameplayAbilities","GameplayTags", "GameplayTasks","NavigationSystem"});

b. 同步查找路径位置

/*同步查找路径位置*/UNavigationPath* NavPath = UNavigationSystemV1::FindPathToLocationSynchronously(this, ControlledPawn->GetActorLocation(), CachedDestination);if (NavPath == nullptr) return;

(6)画样条线:

Spline->ClearSplinePoints(); //清除样条内现有的点for(const FVector& PointLoc : NavPath->PathPoints){Spline->AddSplinePoint(PointLoc, ESplineCoordinateSpace::World); //将新的位置添加到样条曲线中DrawDebugSphere(GetWorld(), PointLoc, 8.f, 8, FColor::Orange, false, 5.f); //点击后debug调试}//自动寻路将最终目的地设置为导航的终点,方便停止导航CachedDestination = NavPath->PathPoints[NavPath->PathPoints.Num() - 1];bAutoRunning = true; //设置当前正常自动寻路状态,将在tick中更新位置

2.蓝图地图里,添加导航网格体边界体积:

全图覆盖:按P键查看范围

3.添加障碍物:

确保他有碰撞:

效果:

4.在帧循环实现自动移动:

(1)创建AutoRun()函数,在Tick()里调用:

void ACC_PlayerController::PlayerTick(float DeltaTime)
{Super::PlayerTick(DeltaTime);CurserTrace();AutoRun();
}

(2)AutoRun()方法:

void ACC_PlayerController::AutoRun()
{if(!bAutoRunning) return;APawn* ControlledPawn = GetPawn();if(ControlledPawn == nullptr) return;//找到距离样条最近的位置const FVector LocationOnSpline = Spline->FindLocationClosestToWorldLocation(ControlledPawn->GetActorLocation(), ESplineCoordinateSpace::World);//获取这个位置在样条上的方向const FVector Direction = Spline->FindDirectionClosestToWorldLocation(LocationOnSpline, ESplineCoordinateSpace::World);ControlledPawn->AddMovementInput(Direction);const float DistanceToDestination = (LocationOnSpline - CachedDestination).Length();if(DistanceToDestination <= AutoRunAcceptanceRadius){bAutoRunning = false;}
}

(3)如果需要服务器,我们需要在导航系统设置运行客户端导航,这样,会在所有的客户端生成导航体积。

源代码:

Source/CC_Aura/Public/Player/CC_PlayerController.h:

// 版权归陈超所有#pragma once#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "CC_PlayerController.generated.h"class USplineComponent;
class UCC_AbilitySystemComponent;
struct FGameplayTag;
class UDataAsset_InputConfig;
class ICC_EnemyInterface;
class UInputMappingContext;
class UInputAction;/*** */
UCLASS()
class CC_AURA_API ACC_PlayerController : public APlayerController
{GENERATED_BODY()public:ACC_PlayerController();virtual void PlayerTick(float DeltaTime) override;
protected:virtual void BeginPlay() override;UPROPERTY()TObjectPtr<UCC_AbilitySystemComponent> CC_AbilitySystemComponent;		//能力系统组件UCC_AbilitySystemComponent* GetCC_AbilitySystemComponent();/*鼠标追踪* 1.高亮敌人类*/
#pragma region CurserTrace
private://鼠标追踪变量TScriptInterface<ICC_EnemyInterface> LastActor;	//上一帧拾取的接口指针TScriptInterface<ICC_EnemyInterface> ThisActor;	//当前帧拾取的接口指针void CurserTrace();	//鼠标追踪函数
#pragma endregion/*输入设置* 1.移动输入* 2.能力输入*/
#pragma region Inputs
protected:virtual void SetupInputComponent() override;
private:UPROPERTY(EditAnywhere, Category="CC|Input")TObjectPtr<UDataAsset_InputConfig> DataAssetInputConfig;void Move(const struct FInputActionValue& InputActionValue);void AbilityInputTagPressed(FGameplayTag InputTag);		//按下void AbilityInputTagReleased(FGameplayTag InputTag);	//结束void AbilityInputTagHold(FGameplayTag InputTag);		//持续
#pragma endregion/*鼠标点击移动*/
#pragma region ClickToMoveprivate:FVector CachedDestination = FVector::ZeroVector;	//追击的目的地float FollowTime = 0.f;		//鼠标按住的时间float ShortPressThreshold = 0.5f;		//短按阈值bool bAutoRunning =false;		//是否自动追踪bool bTargetting = false;		//目标锁定UPROPERTY(EditDefaultsOnly, Category="CC|ClickToMove")float AutoRunAcceptanceRadius = 50.f;		//自动追踪到达目的地的半径后停止UPROPERTY(VisibleAnywhere, Category="CC|ClickToMove")TObjectPtr<USplineComponent> Spline;		//样条曲线void AutoRun();		//自动寻路
#pragma endregion};

Source/CC_Aura/Private/Player/CC_PlayerController.cpp

// 版权归陈超所有#include "Player/CC_PlayerController.h"#include "AbilitySystemBlueprintLibrary.h"
#include "AbilitySystem/CC_AbilitySystemComponent.h"
#include "CC_GameplayTags.h"
#include "Components/SplineComponent.h"
#include "EnhancedInputSubsystems.h"
#include "EnhancedInputComponent.h"
#include "NavigationPath.h"
#include "NavigationSystem.h"
#include "Input/CC_InputComponent.h"
#include "Interations/CC_EnemyInterface.h"ACC_PlayerController::ACC_PlayerController()
{bReplicates = true;		//确保可复制Spline = CreateDefaultSubobject<USplineComponent>("Spline");}void ACC_PlayerController::PlayerTick(float DeltaTime)
{Super::PlayerTick(DeltaTime);CurserTrace();AutoRun();
}void ACC_PlayerController::AutoRun()
{if(!bAutoRunning) return;APawn* ControlledPawn = GetPawn();if(ControlledPawn == nullptr) return;//找到距离样条最近的位置const FVector LocationOnSpline = Spline->FindLocationClosestToWorldLocation(ControlledPawn->GetActorLocation(), ESplineCoordinateSpace::World);//获取这个位置在样条上的方向const FVector Direction = Spline->FindDirectionClosestToWorldLocation(LocationOnSpline, ESplineCoordinateSpace::World);ControlledPawn->AddMovementInput(Direction);const float DistanceToDestination = (LocationOnSpline - CachedDestination).Length();if(DistanceToDestination <= AutoRunAcceptanceRadius){bAutoRunning = false;}
}//鼠标位置追踪
void ACC_PlayerController::CurserTrace()
{FHitResult CursorHit;GetHitResultUnderCursor(ECC_Visibility, false, CursorHit);	//获取可视的鼠标命中结果if(!CursorHit.bBlockingHit) return; //如果未命中直接返回LastActor = ThisActor;ThisActor = CursorHit.GetActor();/*** 射线拾取后,会出现的几种情况* 1. LastActor is null   ThisActor is null 不需要任何操作* 2. LastActor is null   ThisActor is valid 高亮ThisActor* 3. LastActor is valid   ThisActor is null 取消高亮LastActor* 4. LastActor is valid   ThisActor is valid LastActor != ThisActor 取消高亮LastActor 高亮ThisActor* 5. LastActor is valid   ThisActor is valid LastActor == ThisActor 不需要任何操作*/if(LastActor == nullptr){if(ThisActor != nullptr){//case 2ThisActor->HighlightActor();} // else case 1}else{if(ThisActor == nullptr){//case 3LastActor->UnHighlightActor();}else{if(LastActor != ThisActor){//case 4LastActor->UnHighlightActor();ThisActor->HighlightActor();} //else case 5}}	
}void ACC_PlayerController::BeginPlay()
{Super::BeginPlay();//设置鼠标光标bShowMouseCursor = true; //游戏中是否显示鼠标光标DefaultMouseCursor = EMouseCursor::Default; //鼠标光标的样式FInputModeGameAndUI InputModeData;InputModeData.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock); //将鼠标锁定在视口内InputModeData.SetHideCursorDuringCapture(false); //鼠标被捕获时是否隐藏SetInputMode(InputModeData); //设置给控制器}UCC_AbilitySystemComponent* ACC_PlayerController::GetCC_AbilitySystemComponent()
{if (CC_AbilitySystemComponent == nullptr){UAbilitySystemComponent* AbilitySystemComponent = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(GetPawn<APawn>());CC_AbilitySystemComponent = Cast<UCC_AbilitySystemComponent>(AbilitySystemComponent);}return CC_AbilitySystemComponent;
}//设置输入组件函数(重载)
void ACC_PlayerController::SetupInputComponent()
{Super::SetupInputComponent();checkf(DataAssetInputConfig,TEXT("DataAssetInputConfig 指针为空!"));UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer());if(Subsystem == nullptr) return;//添加映射上下文Subsystem->AddMappingContext(DataAssetInputConfig->DefaultMappingContext, 0);UCC_InputComponent* CC_InputComponent = CastChecked<UCC_InputComponent>(InputComponent); //将InputComponent转换成增强输入组件CC_InputComponent->BindInputAction(DataAssetInputConfig, CC_GameplayTags::Input_Move, ETriggerEvent::Triggered, this, &ThisClass::Move); //绑定移动事件CC_InputComponent->BindAbilityAction(DataAssetInputConfig, this, &ThisClass::AbilityInputTagPressed, &ThisClass::AbilityInputTagReleased, &ThisClass::AbilityInputTagHold);
}//移动事件的返回函数
void ACC_PlayerController::Move(const struct FInputActionValue& InputActionValue)
{const FVector2D InputAxisVector = InputActionValue.Get<FVector2D>(); //获取输入操作的2维向量值const FRotator Rotation = GetControlRotation(); //获取控制器旋转const FRotator YawRotation(0.f, Rotation.Yaw, 0.f); //通过控制器的垂直朝向创建一个旋转值,忽略上下朝向和左右朝向const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X); //获取向前的值(旋转矩阵)const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y); //获取向右的值,-1到1if(APawn* ControlledPawn = GetPawn<APawn>()){ControlledPawn->AddMovementInput(ForwardDirection, InputAxisVector.Y);ControlledPawn->AddMovementInput(RightDirection, InputAxisVector.X);}}/*开始按下*/
void ACC_PlayerController::AbilityInputTagPressed(FGameplayTag InputTag)
{/*如果是鼠标左键*/if (InputTag.MatchesTagExact(CC_GameplayTags::Input_LMB)){bTargetting = ThisActor ? true : false;		//是否有敌人?bAutoRunning = false;		//不需要自动追踪}
}/*释放*/
void ACC_PlayerController::AbilityInputTagReleased(FGameplayTag InputTag)
{/*如果不是鼠标左键*/if (!InputTag.MatchesTagExact(CC_GameplayTags::Input_LMB)){if (GetCC_AbilitySystemComponent() == nullptr) return;GetCC_AbilitySystemComponent()->AbilityInputTagReleased(InputTag);return;}/*如果是鼠标左键*/if (bTargetting)	//是敌人类{if (GetCC_AbilitySystemComponent() == nullptr) return;GetCC_AbilitySystemComponent()->AbilityInputTagReleased(InputTag);return;}if(FollowTime > ShortPressThreshold)	return;		//长按,退出/*短按*/APawn* ControlledPawn = GetPawn();if (ControlledPawn == nullptr) return;/*同步查找路径位置*/UNavigationPath* NavPath = UNavigationSystemV1::FindPathToLocationSynchronously(this, ControlledPawn->GetActorLocation(), CachedDestination);if (NavPath == nullptr) return;Spline->ClearSplinePoints(); //清除样条内现有的点for(const FVector& PointLoc : NavPath->PathPoints){Spline->AddSplinePoint(PointLoc, ESplineCoordinateSpace::World); //将新的位置添加到样条曲线中DrawDebugSphere(GetWorld(), PointLoc, 8.f, 8, FColor::Cyan, false, 5.f); //点击后debug调试}//自动寻路将最终目的地设置为导航的终点,方便停止导航if (NavPath->PathPoints.Num() > 0){CachedDestination = NavPath->PathPoints[NavPath->PathPoints.Num() - 1];}bAutoRunning = true; //设置当前正常自动寻路状态,将在tick中更新位置FollowTime = 0.f;bTargetting = false;
}/*保持*/
void ACC_PlayerController::AbilityInputTagHold(FGameplayTag InputTag)
{/*如果不是鼠标左键*/if (!InputTag.MatchesTagExact(CC_GameplayTags::Input_LMB)){if (GetCC_AbilitySystemComponent() == nullptr) return;GetCC_AbilitySystemComponent()->AbilityInputTagHeld(InputTag);return;}/*如果是鼠标左键*/if (bTargetting)	//是敌人类{if (GetCC_AbilitySystemComponent() == nullptr) return;GetCC_AbilitySystemComponent()->AbilityInputTagHeld(InputTag);return;}//非敌人类FollowTime += GetWorld()->GetDeltaSeconds();FHitResult Hit;if (GetHitResultUnderCursor(ECC_Visibility, false, Hit)){CachedDestination = Hit.ImpactPoint;		//缓存点击位置}if (APawn* ControlledPawn = GetPawn<APawn>()){const FVector WorldDirection = (CachedDestination - ControlledPawn->GetActorLocation()).GetSafeNormal();ControlledPawn->AddMovementInput(WorldDirection);}if(!bAutoRunning) FollowTime = 0.f;
}

http://www.dtcms.com/a/594004.html

相关文章:

  • 培训人员网站建设龙岗网站开发公司
  • 【经验分享】Genio 520/Genio720未使用引脚处理方法
  • 重庆免费网站建站模板微网站趋势
  • DDR5引领变革:内存条行业的技术迭代与市场重构
  • 一小时速通Pytorch之Tensor张量(一)
  • 怎么做网站教程 用的工具提供网站推广公司电话
  • 网站服务内容怎么写wordpress 响应时间
  • 主成分分析(Principal Component Analysis,PCA)的个人理解
  • sqlite数据库迁移至mysql
  • PostgreSQL 高并发优化:从 “连接数满到崩” 到 “支撑 10 万 QPS” 的实战技巧
  • 怎么免费建自己的网站网络营销课程培训机构
  • 团队开发者git仓库工作手册
  • 欧美风网站建设seo品牌优化整站优化
  • 2.8 模型压缩与优化技术
  • 数字孪生工厂浪潮来袭,众趣科技以实景智能筑牢智造基石
  • [設計模式]二十三種設計模式
  • 有视频接口怎么做网站哪个行业最需要做网站
  • 解锁AI工作流的终极密码:Semantic Kernel Process框架深度技术解析
  • 从0到1:Makefile自动化编译实战全解析
  • 广州网站推广教程中国建设银行网站会员用户名
  • 怎么做分享软件的网站php网站开发框架搭建
  • 网站跟网页的区别jsp做的网页是网站吗
  • 根据docker服务保存日志脚本,时间可选版本
  • 九、神经网络的构建方式详解
  • 第五章 神经网络
  • 网站建设相关的工作鸿顺里网站建设公司
  • 自己做网站卖手机网站建设电话
  • TypeScript 元组
  • LLM - 大模型融合 LangChain 与 OpenRouter 的框架
  • 南宁建企业网站公司办公室装修设计怎么收费