1.调整一下输入资产,将输入映射上下文添加进去:


2.新增自定义输入组件,创建函数BindAbilityAction:
Source/CC_Aura/Public/Input/CC_InputComponent.h
cpp
// 版权归陈超所有
#pragma once
#include "CoreMinimal.h"
#include "DataAsset_InputConfig.h"
#include "EnhancedInputComponent.h"
#include "CC_InputComponent.generated.h"
class UDataAsset_InputConfig;
/**
*
*/
UCLASS()
class CC_AURA_API UCC_InputComponent : public UEnhancedInputComponent
{
GENERATED_BODY()
public:
template<class UserObject, typename CallbackFunc>
void BindAbilityAction(const UDataAsset_InputConfig* InInputConfig, const FGameplayTag& InInputTag, ETriggerEvent TriggerEvent ,UserObject* ContextObject, CallbackFunc Func);
};
template <class UserObject, typename CallbackFunc>
void UCC_InputComponent::BindAbilityAction(const UDataAsset_InputConfig* InInputConfig, const FGameplayTag& InInputTag,
ETriggerEvent TriggerEvent, UserObject* ContextObject, CallbackFunc Func)
{
checkf(InInputConfig, TEXT("[%s]里的InInputConfig为空指针,无法继续执行绑定操作!"),*GetName());
UInputAction* InputAction = InInputConfig->GetInputActionByTag(InInputTag);
if (InputAction == nullptr) return;
BindAction(InputAction, TriggerEvent, ContextObject, Func);
}
在编辑器项目设置里,将"默认输入组件类"改成自己的输入组件类:

3.在CC_PlayerController.h中添加输入数据资产,顺便把其他的输入映射上下文和输入动作删除:
cpp
// 版权归陈超所有
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "CC_PlayerController.generated.h"
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;
#pragma region CurserTrace
private:
//鼠标追踪变量
TScriptInterface<ICC_EnemyInterface> LastActor; //上一帧拾取的接口指针
TScriptInterface<ICC_EnemyInterface> ThisActor; //当前帧拾取的接口指针
void CurserTrace(); //鼠标追踪函数
#pragma endregion
#pragma region Inputs
protected:
virtual void SetupInputComponent() override;
private:
UPROPERTY(EditAnywhere, Category="CC|Input")
TObjectPtr<UDataAsset_InputConfig> DataAssetInputConfig;
void Move(const struct FInputActionValue& InputActionValue);
#pragma endregion
};
Source/CC_Aura/Private/Player/CC_PlayerController.cpp

源码:
cpp
// 版权归陈超所有
#include "Player/CC_PlayerController.h"
#include "CC_GameplayTags.h"
#include "EnhancedInputSubsystems.h"
#include "EnhancedInputComponent.h"
#include "Input/CC_InputComponent.h"
#include "Interations/CC_EnemyInterface.h"
ACC_PlayerController::ACC_PlayerController()
{
bReplicates = true; //确保可复制
}
void ACC_PlayerController::PlayerTick(float DeltaTime)
{
Super::PlayerTick(DeltaTime);
CurserTrace();
}
//鼠标位置追踪
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 2
ThisActor->HighlightActor();
} // else case 1
}
else
{
if(ThisActor == nullptr)
{
//case 3
LastActor->UnHighlightActor();
}
else
{
if(LastActor != ThisActor)
{
//case 4
LastActor->UnHighlightActor();
ThisActor->HighlightActor();
} //else case 5
}
}
}
void ACC_PlayerController::BeginPlay()
{
Super::BeginPlay();
/*
check(CCContext);//判断增强输入映射情境是否存在
//从本地角色身上获取到它的子系统
UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer());
// check(Subsystem);//检查子系统是否存在
if (Subsystem)
{
Subsystem->AddMappingContext(CCContext,0);//子系统配置情境
}
*/
//设置鼠标光标
bShowMouseCursor = true; //游戏中是否显示鼠标光标
DefaultMouseCursor = EMouseCursor::Default; //鼠标光标的样式
FInputModeGameAndUI InputModeData;
InputModeData.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock); //将鼠标锁定在视口内
InputModeData.SetHideCursorDuringCapture(false); //鼠标被捕获时是否隐藏
SetInputMode(InputModeData); //设置给控制器
}
//设置输入组件函数(重载)
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->BindAbilityAction(DataAssetInputConfig, CC_GameplayTags::Input_Move, ETriggerEvent::Triggered, this, &ThisClass::Move); //绑定移动事件
}
//移动事件的返回函数
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到1
if(APawn* ControlledPawn = GetPawn<APawn>())
{
ControlledPawn->AddMovementInput(ForwardDirection, InputAxisVector.Y);
ControlledPawn->AddMovementInput(RightDirection, InputAxisVector.X);
}
}
在编辑器玩家控制器类中,添加输入配置资产:
