Files
BlueRoseNote/03-UnrealEngine/Gameplay/Lyra/UE5 Lyra学习笔记(8)—EnhanceInput(UE5.5).md

217 lines
9.4 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Untitled
date: 2025-08-27 17:03:13
excerpt:
tags:
rating: ⭐
---
# 前言
- 官方文档
- [Enhanced Input](https://dev.epicgames.com/documentation/en-us/unreal-engine/enhanced-input-in-unreal-engine?application_version=5.5)
- [Using CommonUI With Enhanced Input](https://dev.epicgames.com/documentation/en-us/unreal-engine/using-commonui-with-enhnaced-input-in-unreal-engine?application_version=5.5)
- 知乎文章
- [UE5 -- Lyra中的输入模块(Input)](https://zhuanlan.zhihu.com/p/537949870)
- [UE5 Lyra的多模态输入和修改灵敏度配置方案](https://zhuanlan.zhihu.com/p/30566880169)
## 调试命令
- showdebug enhancedinput会显示你的项目的可用输入动作和轴映射。
- showdebug devices
# 相关类
- **Input Actions**:配置输入动作 => 数据或者状态用的资产。
- **Input Mapping Contexts**输入Action的集合。可以为不同GameMode配置不同的 **Input Mapping Contexts**来满足自定义输入的需求。
- **Input Modifiers** 是一种预处理器能够修改UE接收的原始输入值然后再将其发送给输入触发器Input Trigger。增强输入插件随附多种输入修饰器可以执行各种任务例如更改轴顺序、实现"死区"、将轴输入转换为世界空间。
- **Input Triggers**:用于确定用户输入在经过一系列可选输入修饰器的处理后,是否会激活输入映射上下文中的相应输入动作。
- 多平台相关位于Project Settings -> Enhanced Input -> Platform Settings -> Input Data
- Mapping Context Redirect将不同的输入设置用于不同的平台。
- Enhanced Input Platform Data为你的游戏添加特定于平台的选项。
**InputAction**绑定:
```c++
void AFooBar::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
UEnhancedInputComponent* Input = Cast<UEnhancedInputComponent>(PlayerInputComponent);
// 你可以通过更改"ETriggerEvent"枚举值,绑定到此处的任意触发器事件
Input->BindAction(AimingInputAction, ETriggerEvent::Triggered, this, &AFooBar::SomeCallbackFunc);
}
void AFooBar::SomeCallbackFunc(const FInputActionInstance& Instance)
{
// 获取此处所需任意类型的输入动作的值...
FVector VectorValue = Instance.GetValue().Get<FVector>();
FVector2D 2DAxisValue = Instance.GetValue().Get<FVector2D>();
float FloatValue = Instance.GetValue().Get<float>();
bool BoolValue = Instance.GetValue().Get<bool>();
// 在此处实现你的精彩功能!
}
```
Runtime **InputMappingContext**添加:
```c++
// 将映射上下文公开为头文件中的属性...
UPROPERTY(EditAnywhere, Category="Input")
TSoftObjectPtr<UInputMappingContext> InputMapping;
// 在你的cpp中...
if (ULocalPlayer* LocalPlayer = Cast<ULocalPlayer>(Player))
{
if (UEnhancedInputLocalPlayerSubsystem* InputSystem = LocalPlayer->GetSubsystem<UEnhancedInputLocalPlayerSubsystem>())
{
if (!InputMapping.IsNull())
{
InputSystem->AddMappingContext(InputMapping.LoadSynchronous(), Priority);
}
}
}
```
**Input Trigger Timed Base** 会检查输入是否已被按住一段时间,如是,则接受该输入并返回 **持续Ongoing** 状态。
```c++
/** UInputTriggerHold
触发器会在输入保持激活状态达到HoldTimeThreshold秒之后触发。
触发器可以选择触发一次或反复触发。
*/
UCLASS(NotBlueprintable, MinimalAPI, meta = (DisplayName = "Hold"))
class UInputTriggerHold final : public UInputTriggerTimedBase
{
GENERATED_BODY()
bool bTriggered = false;
protected:
virtual ETriggerState UpdateState_Implementation(const UEnhancedPlayerInput* PlayerInput, FInputActionValue ModifiedValue, float DeltaTime) override;
public:
virtual ETriggerEventsSupported GetSupportedTriggerEvents() const override { return ETriggerEventsSupported::Ongoing; }
// 输入要保持多久才能导致触发?
UPROPERTY(EditAnywhere, Config, BlueprintReadWrite, Category = "Trigger Settings", meta = (ClampMin = "0"))
float HoldTimeThreshold = 1.0f;
// 此触发器应该仅触发一次,还是在满足保持时间阈值之后每帧触发?
UPROPERTY(EditAnywhere, Config, BlueprintReadWrite, Category = "Trigger Settings")
bool bIsOneShot = false;
virtual FString GetDebugState() const override { return HeldDuration ? FString::Printf(TEXT("Hold:%.2f/%.2f"), HeldDuration, HoldTimeThreshold) : FString(); }
};
ETriggerState UInputTriggerHold::UpdateState_Implementation(const UEnhancedPlayerInput* PlayerInput, FInputActionValue ModifiedValue, float DeltaTime)
{
// 更新HeldDuration并派生基础状态
ETriggerState State = Super::UpdateState_Implementation(PlayerInput, ModifiedValue, DeltaTime);
// 在HeldDuration达到阈值时触发
bool bIsFirstTrigger = !bTriggered;
bTriggered = HeldDuration >= HoldTimeThreshold;
if (bTriggered)
{
return (bIsFirstTrigger || !bIsOneShot) ? ETriggerState::Triggered : ETriggerState::None;
}
return State;
}
```
# 按键设置
# Lyra中的相关实现
## ULyraHeroComponent中的输入绑定
```c++
void ULyraHeroComponent::InitializePlayerInput(UInputComponent* PlayerInputComponent)
{
check(PlayerInputComponent);
const APawn* Pawn = GetPawn<APawn>();
if (!Pawn)
{
return;
}
const APlayerController* PC = GetController<APlayerController>();
check(PC);
const ULyraLocalPlayer* LP = Cast<ULyraLocalPlayer>(PC->GetLocalPlayer());
check(LP);
UEnhancedInputLocalPlayerSubsystem* Subsystem = LP->GetSubsystem<UEnhancedInputLocalPlayerSubsystem>();
check(Subsystem);
Subsystem->ClearAllMappings();
if (const ULyraPawnExtensionComponent* PawnExtComp = ULyraPawnExtensionComponent::FindPawnExtensionComponent(Pawn))
{
if (const ULyraPawnData* PawnData = PawnExtComp->GetPawnData<ULyraPawnData>())
{
//获取ULyraInputConfig DataAesset,存储TArray<FLyraInputAction>FLyraInputAction里为InputAction、GameplayTag。
if (const ULyraInputConfig* InputConfig = PawnData->InputConfig)
{
for (const FInputMappingContextAndPriority& Mapping : DefaultInputMappings)
{
//获取UInputMappingContext并进行注册。
if (UInputMappingContext* IMC = Mapping.InputMapping.Get())
{
if (Mapping.bRegisterWithSettings)
{
if (UEnhancedInputUserSettings* Settings = Subsystem->GetUserSettings())
{
Settings->RegisterInputMappingContext(IMC);
}
FModifyContextOptions Options = {};
Options.bIgnoreAllPressedKeysUntilRelease = false;
// Actually add the config to the local player
Subsystem->AddMappingContext(IMC, Mapping.Priority, Options);
}
}
}
// The Lyra Input Component has some additional functions to map Gameplay Tags to an Input Action.
// If you want this functionality but still want to change your input component class, make it a subclass
// of the ULyraInputComponent or modify this component accordingly.
ULyraInputComponent* LyraIC = Cast<ULyraInputComponent>(PlayerInputComponent);
if (ensureMsgf(LyraIC, TEXT("Unexpected Input Component class! The Gameplay Abilities will not be bound to their inputs. Change the input component to ULyraInputComponent or a subclass of it.")))
{
// Add the key mappings that may have been set by the player
LyraIC->AddInputMappings(InputConfig, Subsystem);
// This is where we actually bind and input action to a gameplay tag, which means that Gameplay Ability Blueprints will
// be triggered directly by these input actions Triggered events.
TArray<uint32> BindHandles;
LyraIC->BindAbilityActions(InputConfig, this, &ThisClass::Input_AbilityInputTagPressed, &ThisClass::Input_AbilityInputTagReleased, /*out*/ BindHandles);
LyraIC->BindNativeAction(InputConfig, LyraGameplayTags::InputTag_Move, ETriggerEvent::Triggered, this, &ThisClass::Input_Move, /*bLogIfNotFound=*/ false);
LyraIC->BindNativeAction(InputConfig, LyraGameplayTags::InputTag_Look_Mouse, ETriggerEvent::Triggered, this, &ThisClass::Input_LookMouse, /*bLogIfNotFound=*/ false);
LyraIC->BindNativeAction(InputConfig, LyraGameplayTags::InputTag_Look_Stick, ETriggerEvent::Triggered, this, &ThisClass::Input_LookStick, /*bLogIfNotFound=*/ false);
LyraIC->BindNativeAction(InputConfig, LyraGameplayTags::InputTag_Crouch, ETriggerEvent::Triggered, this, &ThisClass::Input_Crouch, /*bLogIfNotFound=*/ false);
LyraIC->BindNativeAction(InputConfig, LyraGameplayTags::InputTag_AutoRun, ETriggerEvent::Triggered, this, &ThisClass::Input_AutoRun, /*bLogIfNotFound=*/ false);
}
}
}
}
if (ensure(!bReadyToBindInputs))
{
bReadyToBindInputs = true;
}
UGameFrameworkComponentManager::SendGameFrameworkComponentExtensionEvent(const_cast<APlayerController*>(PC), NAME_BindInputsNow);
UGameFrameworkComponentManager::SendGameFrameworkComponentExtensionEvent(const_cast<APawn*>(Pawn), NAME_BindInputsNow);
}
```
# 按键设置与保存
- [Player Mappable Keys using Enhanced Input](https://dev.epicgames.com/community/learning/tutorials/Vp69/unreal-engine-player-mappable-keys-using-enhanced-input)
## 相关类
- **UEnhancedInputUserSettings** ~~PlayerMappableInputConfig~~ 用户输入设置类。通过EnhancedInputLocalPlayerSubsystem->GetEnhancedInputUserSettings()获取。
- UEnhancedPlayerMappableKeyProfile一个用户当前设置的实例。比如“默认”与“左撇子"。
## 步骤
1. 假设已经配置好了IMC以及IA。
1. 在Controller中注册IMC与IA
2. ProjectSettings - Engine - EnhancedInput - UserSettings中的Enable User Settings
3. 配置IA中的UserSetting选项。
1.