ue-input-system
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseUE Enhanced Input System
UE Enhanced Input 系统
You are an expert in Unreal Engine's Enhanced Input system.
你是Unreal Engine的Enhanced Input系统专家。
Context Check
上下文检查
Read before proceeding. Confirm:
.agents/ue-project-context.md- plugin is listed as enabled
EnhancedInput - Target platforms (affects which modifiers are needed per platform)
- Whether CommonUI is in use (it manages input mode switching automatically)
- Whether the project still uses legacy input (migration may be needed)
在继续操作前,请阅读。确认:
.agents/ue-project-context.md- 插件已列为启用状态
EnhancedInput - 目标平台(影响各平台所需的修改器类型)
- 是否使用CommonUI(它会自动管理输入模式切换)
- 项目是否仍在使用旧版输入系统(可能需要迁移)
Information Gathering
信息收集
Ask the developer: what actions are needed and their value types (Bool/Axis1D/Axis2D/Axis3D), which platforms, any complex input requirements (hold-to-charge, double-tap, combos, chord shortcuts), and whether multiple input modes are required (gameplay vs UI vs vehicle).
询问开发者:需要实现哪些操作及其值类型(Bool/Axis1D/Axis2D/Axis3D)、目标平台、是否有复杂输入需求(按住蓄力、双击、组合键、和弦快捷键),以及是否需要多种输入模式(游戏玩法/UI/载具)。
Enhanced Input Setup
Enhanced Input 设置
Plugin and Module
插件与模块
.uproject{ "Name": "EnhancedInput", "Enabled": true }Build.cs"EnhancedInput"PublicDependencyModuleNamesDefaultInput.iniini
[/Script/Engine.InputSettings]
DefaultPlayerInputClass=/Script/EnhancedInput.EnhancedPlayerInput
DefaultInputComponentClass=/Script/EnhancedInput.EnhancedInputComponent.uproject{ "Name": "EnhancedInput", "Enabled": true }Build.csPublicDependencyModuleNames"EnhancedInput"DefaultInput.iniini
[/Script/Engine.InputSettings]
DefaultPlayerInputClass=/Script/EnhancedInput.EnhancedPlayerInput
DefaultInputComponentClass=/Script/EnhancedInput.EnhancedInputComponentUInputAction Asset
UInputAction 资源
UInputAction : UDataAssetInputAction.hcpp
EInputActionValueType ValueType = EInputActionValueType::Boolean;
// Boolean | Axis1D (float) | Axis2D (FVector2D) | Axis3D (FVector)
EInputActionAccumulationBehavior AccumulationBehavior
= EInputActionAccumulationBehavior::TakeHighestAbsoluteValue;
// TakeHighestAbsoluteValue — highest magnitude wins across all mappings to this action
// Cumulative — all mapping values sum (W + S cancel each other for WASD)
bool bConsumeInput = true; // blocks lower-priority Enhanced Input mappings to same keys
TArray<TObjectPtr<UInputTrigger>> Triggers; // applied AFTER per-mapping triggers
TArray<TObjectPtr<UInputModifier>> Modifiers; // applied AFTER per-mapping modifiersUInputAction : UDataAssetInputAction.hcpp
EInputActionValueType ValueType = EInputActionValueType::Boolean;
// Boolean | Axis1D(浮点型) | Axis2D(FVector2D) | Axis3D(FVector)
EInputActionAccumulationBehavior AccumulationBehavior
= EInputActionAccumulationBehavior::TakeHighestAbsoluteValue;
// TakeHighestAbsoluteValue — 所有映射到该操作的输入中,绝对值最大的生效
// Cumulative — 所有映射值相加(W和S在WASD中会相互抵消)
bool bConsumeInput = true; // 阻止低优先级的Enhanced Input映射使用相同按键
TArray<TObjectPtr<UInputTrigger>> Triggers; // 在每个映射的触发器之后应用
TArray<TObjectPtr<UInputModifier>> Modifiers; // 在每个映射的修改器之后应用UInputMappingContext Asset
UInputMappingContext 资源
UInputMappingContext : UDataAsset- —
DefaultKeyMappings.Mappingsof key-to-action entriesTArray<FEnhancedActionKeyMapping> - — per-profile key overrides for player remapping support
MappingProfileOverrides - :
RegistrationTrackingMode(default, first Remove wins) orUntracked(IMC stays until Remove called N times, safe when multiple systems share it)CountRegistrations
UInputMappingContext : UDataAsset- — 按键到操作的
DefaultKeyMappings.Mappings条目TArray<FEnhancedActionKeyMapping> - — 针对玩家重映射支持的每个配置文件的按键覆盖
MappingProfileOverrides - :
RegistrationTrackingMode(默认,首次移除生效)或Untracked(IMC需调用N次Remove才会移除,适合多系统共享的场景)CountRegistrations
Binding Actions in C++
在C++中绑定操作
SetupPlayerInputComponent
SetupPlayerInputComponent
cpp
// MyCharacter.h — declare assets and handlers
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
TObjectPtr<UInputMappingContext> DefaultMappingContext;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
TObjectPtr<UInputAction> MoveAction;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
TObjectPtr<UInputAction> JumpAction;
void Move(const FInputActionValue& Value);
void StartJump();
void StopJump();cpp
// MyCharacter.cpp
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
UEnhancedInputComponent* EIC = Cast<UEnhancedInputComponent>(PlayerInputComponent);
if (!EIC) { return; }
EIC->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AMyCharacter::Move);
EIC->BindAction(JumpAction, ETriggerEvent::Started, this, &AMyCharacter::StartJump);
EIC->BindAction(JumpAction, ETriggerEvent::Completed, this, &AMyCharacter::StopJump);
}
void AMyCharacter::BeginPlay()
{
Super::BeginPlay();
if (APlayerController* PC = Cast<APlayerController>(GetController()))
{
if (auto* Sub = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(
PC->GetLocalPlayer()))
{
Sub->AddMappingContext(DefaultMappingContext, 0); // priority 0 = lowest
}
}
}cpp
// MyCharacter.h — 声明资源和处理函数
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
TObjectPtr<UInputMappingContext> DefaultMappingContext;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
TObjectPtr<UInputAction> MoveAction;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
TObjectPtr<UInputAction> JumpAction;
void Move(const FInputActionValue& Value);
void StartJump();
void StopJump();cpp
// MyCharacter.cpp
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
UEnhancedInputComponent* EIC = Cast<UEnhancedInputComponent>(PlayerInputComponent);
if (!EIC) { return; }
EIC->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AMyCharacter::Move);
EIC->BindAction(JumpAction, ETriggerEvent::Started, this, &AMyCharacter::StartJump);
EIC->BindAction(JumpAction, ETriggerEvent::Completed, this, &AMyCharacter::StopJump);
}
void AMyCharacter::BeginPlay()
{
Super::BeginPlay();
if (APlayerController* PC = Cast<APlayerController>(GetController()))
{
if (auto* Sub = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(
PC->GetLocalPlayer()))
{
Sub->AddMappingContext(DefaultMappingContext, 0); // 优先级0=最低
}
}
}Callback Signatures
回调签名
BindActioncpp
// No params — press/release without value needed
void AMyCharacter::StartJump() { Jump(); }
// FInputActionValue — for axis values
void AMyCharacter::Move(const FInputActionValue& Value)
{
const FVector2D Input = Value.Get<FVector2D>();
AddMovementInput(GetActorForwardVector(), Input.Y);
AddMovementInput(GetActorRightVector(), Input.X);
}
// FInputActionInstance — when elapsed/triggered time is needed
void AMyCharacter::OnChargeAttack(const FInputActionInstance& Instance)
{
const float HeldFor = Instance.GetElapsedTime(); // Started + Ongoing + Triggered
const float ActiveFor = Instance.GetTriggeredTime(); // Triggered only
}
// Lambda variant
EIC->BindActionValueLambda(InteractAction, ETriggerEvent::Triggered,
[this](const FInputActionValue& Value) { TryInteract(); });Storing and removing a binding:
cpp
FEnhancedInputActionEventBinding& B =
EIC->BindAction(DebugAction, ETriggerEvent::Started, this, &AMyCharacter::DebugToggle);
uint32 Handle = B.GetHandle();
// ...
EIC->RemoveBindingByHandle(Handle); // remove one binding
EIC->ClearBindingsForObject(this); // remove all bindings for an objectBindActioncpp
// 无参数 — 无需值的按压/释放操作
void AMyCharacter::StartJump() { Jump(); }
// FInputActionValue — 用于轴值
void AMyCharacter::Move(const FInputActionValue& Value)
{
const FVector2D Input = Value.Get<FVector2D>();
AddMovementInput(GetActorForwardVector(), Input.Y);
AddMovementInput(GetActorRightVector(), Input.X);
}
// FInputActionInstance — 需要获取持续时间/触发时间时使用
void AMyCharacter::OnChargeAttack(const FInputActionInstance& Instance)
{
const float HeldFor = Instance.GetElapsedTime(); // Started + Ongoing + Triggered状态的持续时间
const float ActiveFor = Instance.GetTriggeredTime(); // 仅Triggered状态的持续时间
}
// Lambda变体
EIC->BindActionValueLambda(InteractAction, ETriggerEvent::Triggered,
[this](const FInputActionValue& Value) { TryInteract(); });存储并移除绑定:
cpp
FEnhancedInputActionEventBinding& B =
EIC->BindAction(DebugAction, ETriggerEvent::Started, this, &AMyCharacter::DebugToggle);
uint32 Handle = B.GetHandle();
// ...
EIC->RemoveBindingByHandle(Handle); // 移除单个绑定
EIC->ClearBindingsForObject(this); // 移除某个对象的所有绑定Trigger Events (ETriggerEvent)
触发事件(ETriggerEvent)
Bitmask enum from :
InputTriggers.h| Event | State Transition | Use for |
|---|---|---|
| None -> Ongoing/Triggered | First frame of input; press-once actions |
| *->Triggered, Triggered->Triggered | Every active frame; continuous movement |
| Ongoing->Ongoing | Held but not yet triggered (charge build-up) |
| Ongoing->None | Released before trigger threshold |
| Triggered->None | Input released after triggering; stop continuous actions |
Note: does not fire if any trigger on the same action reports that frame.
CompletedOngoing来自的位掩码枚举:
InputTriggers.h| 事件 | 状态转换 | 适用场景 |
|---|---|---|
| None -> Ongoing/Triggered | 输入的第一帧;单次按压操作 |
| *->Triggered, Triggered->Triggered | 输入激活的每帧;持续移动操作 |
| Ongoing->Ongoing | 按住但尚未触发(蓄力阶段) |
| Ongoing->None | 在达到触发阈值前释放 |
| Triggered->None | 触发后释放输入;停止持续操作 |
注意:如果同一操作的任何触发器在当前帧报告,则不会触发。
OngoingCompletedBuilt-in Triggers
内置触发器
Full parameter listings in .
references/input-action-reference.md| Class | Name | Behavior |
|---|---|---|
| Down | Every frame input exceeds threshold (implicit default) |
| Pressed | Once on first actuation; holding does not repeat |
| Released | Once when input drops below threshold after actuation |
| Hold | After |
| Hold And Release | On release after holding |
| Tap | Released within |
| Repeated Tap | N taps within |
| Pulse | Repeatedly at |
| Chorded Action | Only fires while |
| Combo (Beta) | All |
Trigger type rules for multi-trigger evaluation: (default, at least one must fire), (all must fire), (blocks everything if active).
ExplicitImplicitBlocker完整参数列表请查看。
references/input-action-reference.md| 类 | 名称 | 行为 |
|---|---|---|
| Down | 输入超过阈值的每帧(隐式默认) |
| Pressed | 首次触发时执行一次;按住不会重复触发 |
| Released | 触发后输入低于阈值时执行一次 |
| Hold | 按住超过 |
| Hold And Release | 按住超过 |
| Tap | 在 |
| Repeated Tap | 在 |
| Pulse | 按住时每隔 |
| Chorded Action | 仅当 |
| Combo(测试版) | 在 |
多触发器评估的规则:(默认,至少一个触发即可)、(所有必须触发)、(如果激活则阻止所有触发)。
ExplicitImplicitBlockerBuilt-in Modifiers
内置修改器
Applied in array order. Mapping-level modifiers run before action-level modifiers.
| Class | Name | Effect |
|---|---|---|
| Dead Zone | Zero input below |
| Scalar | Multiply per axis by |
| Scale By Delta Time | Multiply by frame DeltaTime |
| Negate | Invert selected axes ( |
| Swizzle Input Axis Values | Reorder axes; |
| Smooth | Rolling average over recent samples |
| Smooth Delta | Smoothed normalized delta; configurable interpolation ( |
| Response Curve - Exponential | `sign(x)* |
| Response Curve - User Defined | Separate |
| FOV Scaling | Scale by camera FOV for consistent angular speed across zoom levels |
| To World Space | 2D axis -> world space (up/down = world X, left/right = world Y) |
WASD -> Axis2D recipe ():
AccumulationBehavior = Cumulative- :
W→ Y=+1SwizzleAxis(YXZ) - :
S+SwizzleAxis(YXZ)→ Y=-1Negate(bY) - : none → X=+1
D - :
A→ X=-1Negate(bX)
Gamepad stick: per stick mapping.
DeadZone(Radial, LowerThreshold=0.2)Mouse look: per mapping.
[Scalar(0.4,0.4,1), Smooth, FOVScaling]按数组顺序应用。映射级修改器先于操作级修改器运行。
| 类 | 名称 | 效果 |
|---|---|---|
| Dead Zone | 低于 |
| Scalar | 按轴乘以 |
| Scale By Delta Time | 乘以帧DeltaTime |
| Negate | 反转选定轴( |
| Swizzle Input Axis Values | 重新排序轴; |
| Smooth | 最近样本的滚动平均值 |
| Smooth Delta | 平滑归一化增量;可配置插值方式( |
| Response Curve - Exponential | 按轴计算`sign(x)* |
| Response Curve - User Defined | 每个轴单独使用 |
| FOV Scaling | 根据相机FOV缩放,确保不同缩放级别下的角速度一致 |
| To World Space | 将2D轴转换为世界空间(上下=世界X轴,左右=世界Y轴) |
WASD -> Axis2D 配置方案():
AccumulationBehavior = Cumulative- :
W→ Y=+1SwizzleAxis(YXZ) - :
S+SwizzleAxis(YXZ)→ Y=-1Negate(bY) - :无修改 → X=+1
D - :
A→ X=-1Negate(bX)
游戏手柄摇杆:每个摇杆映射添加。
DeadZone(Radial, LowerThreshold=0.2)鼠标视角:每个映射添加。
[Scalar(0.4,0.4,1), Smooth, FOVScaling]Mapping Context Priority
映射上下文优先级
cpp
// Higher integer = higher priority; wins key conflicts
Subsystem->AddMappingContext(GameplayIMC, 0);
Subsystem->AddMappingContext(VehicleIMC, 1);
// FModifyContextOptions — prevent ghost inputs on switch
FModifyContextOptions Opts;
Opts.bIgnoreAllPressedKeysUntilRelease = true;
Subsystem->AddMappingContext(UIIMC, 2, Opts);
// Remove on mode exit
Subsystem->RemoveMappingContext(VehicleIMC);When on a (the default), a higher-priority context that maps the same physical key will consume it, blocking all lower-priority bindings to that key from firing. This is intentional: use priority layering and together to prevent input conflicts between modes (e.g., a vehicle context consuming Spacebar so the character's Jump action never fires while driving).
bConsumeInput = trueUInputActionbConsumeInputcpp
// 数值越高优先级越高;按键冲突时高优先级生效
Subsystem->AddMappingContext(GameplayIMC, 0);
Subsystem->AddMappingContext(VehicleIMC, 1);
// FModifyContextOptions — 切换时防止幽灵输入
FModifyContextOptions Opts;
Opts.bIgnoreAllPressedKeysUntilRelease = true;
Subsystem->AddMappingContext(UIIMC, 2, Opts);
// 退出模式时移除
Subsystem->RemoveMappingContext(VehicleIMC);当的(默认值)时,映射相同物理按键的高优先级上下文会消耗该按键输入,阻止所有低优先级绑定触发。这是有意设计的:结合优先级分层和可防止不同模式间的输入冲突(例如,载具上下文消耗空格键,这样驾驶时角色的跳跃操作不会触发)。
UInputActionbConsumeInput = truebConsumeInputSplit-Screen / Multiple Local Players
分屏/多本地玩家
In split-screen, each local player has their own . Mapping contexts are per-player — adding a context to one player's subsystem does not affect others. To target a specific player, retrieve their subsystem directly from their :
UEnhancedInputLocalPlayerSubsystemULocalPlayercpp
// Access subsystem for a specific local player (e.g., player 2)
if (ULocalPlayer* LP = PlayerController->GetLocalPlayer())
{
if (auto* Sub = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(LP))
{
Sub->AddMappingContext(PlayerTwoIMC, 0);
}
}分屏模式下,每个本地玩家拥有自己的。映射上下文是按玩家独立的 — 向一个玩家的子系统添加上下文不会影响其他玩家。要定位特定玩家,直接从其获取子系统:
UEnhancedInputLocalPlayerSubsystemULocalPlayercpp
// 获取特定本地玩家的子系统(例如,玩家2)
if (ULocalPlayer* LP = PlayerController->GetLocalPlayer())
{
if (auto* Sub = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(LP))
{
Sub->AddMappingContext(PlayerTwoIMC, 0);
}
}Custom Triggers
自定义触发器
Subclass ; override returning :
UInputTriggerUpdateState_ImplementationETriggerState::None / Ongoing / Triggeredcpp
UCLASS(EditInlineNew, meta=(DisplayName="Double Click"))
class MYGAME_API UDoubleClickTrigger : public UInputTrigger
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Trigger Settings")
float DoubleClickThreshold = 0.3f;
protected:
virtual ETriggerType GetTriggerType_Implementation() const override
{ return ETriggerType::Explicit; }
virtual ETriggerState UpdateState_Implementation(
const UEnhancedPlayerInput* PlayerInput, FInputActionValue ModifiedValue, float DeltaTime) override;
private:
float LastPressTime = 0.f;
bool bWasActuated = false;
};
ETriggerState UDoubleClickTrigger::UpdateState_Implementation(
const UEnhancedPlayerInput* PlayerInput, FInputActionValue ModifiedValue, float DeltaTime)
{
const bool bActuated = IsActuated(ModifiedValue); // helper: magnitude >= ActuationThreshold
const float Now = PlayerInput->GetWorld()->GetTimeSeconds();
if (bActuated && !bWasActuated)
{
if ((Now - LastPressTime) <= DoubleClickThreshold)
{ LastPressTime = 0.f; bWasActuated = bActuated; return ETriggerState::Triggered; }
LastPressTime = Now;
}
bWasActuated = bActuated;
return ETriggerState::None;
}UInputTriggerTimedBaseHeldDurationCalculateHeldDuration继承;重写并返回:
UInputTriggerUpdateState_ImplementationETriggerState::None / Ongoing / Triggeredcpp
UCLASS(EditInlineNew, meta=(DisplayName="Double Click"))
class MYGAME_API UDoubleClickTrigger : public UInputTrigger
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Trigger Settings")
float DoubleClickThreshold = 0.3f;
protected:
virtual ETriggerType GetTriggerType_Implementation() const override
{ return ETriggerType::Explicit; }
virtual ETriggerState UpdateState_Implementation(
const UEnhancedPlayerInput* PlayerInput, FInputActionValue ModifiedValue, float DeltaTime) override;
private:
float LastPressTime = 0.f;
bool bWasActuated = false;
};
ETriggerState UDoubleClickTrigger::UpdateState_Implementation(
const UEnhancedPlayerInput* PlayerInput, FInputActionValue ModifiedValue, float DeltaTime)
{
const bool bActuated = IsActuated(ModifiedValue); // 辅助函数:幅度 >= ActuationThreshold
const float Now = PlayerInput->GetWorld()->GetTimeSeconds();
if (bActuated && !bWasActuated)
{
if ((Now - LastPressTime) <= DoubleClickThreshold)
{ LastPressTime = 0.f; bWasActuated = bActuated; return ETriggerState::Triggered; }
LastPressTime = Now;
}
bWasActuated = bActuated;
return ETriggerState::None;
}UInputTriggerTimedBaseHeldDurationCalculateHeldDurationCustom Modifiers
自定义修改器
Subclass ; override :
UInputModifierModifyRaw_Implementationcpp
UCLASS(EditInlineNew, meta=(DisplayName="Clamp Magnitude"))
class MYGAME_API UClampMagnitudeModifier : public UInputModifier
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Settings)
float MaxMagnitude = 1.0f;
protected:
virtual FInputActionValue ModifyRaw_Implementation(
const UEnhancedPlayerInput* PlayerInput, FInputActionValue CurrentValue, float DeltaTime) override
{
FVector V = CurrentValue.Get<FVector>();
if (V.SizeSquared() > MaxMagnitude * MaxMagnitude)
V = V.GetSafeNormal() * MaxMagnitude;
return FInputActionValue(CurrentValue.GetValueType(), V);
}
};继承;重写:
UInputModifierModifyRaw_Implementationcpp
UCLASS(EditInlineNew, meta=(DisplayName="Clamp Magnitude"))
class MYGAME_API UClampMagnitudeModifier : public UInputModifier
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Settings)
float MaxMagnitude = 1.0f;
protected:
virtual FInputActionValue ModifyRaw_Implementation(
const UEnhancedPlayerInput* PlayerInput, FInputActionValue CurrentValue, float DeltaTime) override
{
FVector V = CurrentValue.Get<FVector>();
if (V.SizeSquared() > MaxMagnitude * MaxMagnitude)
V = V.GetSafeNormal() * MaxMagnitude;
return FInputActionValue(CurrentValue.GetValueType(), V);
}
};Common Mistakes
常见错误
- Mapping context not added: Add via subsystem in /after
BeginPlay, not inPossess(called earlier on some paths).SetupPlayerInputComponent - Legacy binding on UEnhancedInputComponent: and
BindAction(FName,...)areBindAxis. Compile error. Set= deleteinDefaultInputComponentClass.DefaultInput.ini - Triggered for a button press: fires every active frame. Use
Triggeredfor press-once,Startedfor release.Completed - Completed not firing with Ongoing: If any trigger reports that frame,
Ongoingis suppressed. Use separate actions for clean press/release events.Completed - No dead zone on gamepad sticks: Sticks produce non-zero resting values. Always add per stick mapping.
DeadZone(Radial) - Missing SwizzleAxis for WASD-to-2D: Keyboard produces 1D. Without on W/S, forward/backward stays on X and is ignored by Axis2D forward movement.
SwizzleAxis(YXZ) - Replicating input actions: Input is client-local. Replicate results (movement, ability activation), not trigger events.
- MapKey/UnmapKey at runtime for rebinding: These are editor/config-screen helpers. Use subsystem player mappable key APIs or swap contexts instead.
- Wrong trigger type for intent: Using when
Downis needed, orHoldwhenTriggeredis needed. Match trigger type to the interaction pattern:Startedfor single press,Startedfor continuous,Triggeredfor delayed activation.Hold
- 未添加映射上下文:在/
BeginPlay之后通过子系统添加,不要在Possess中添加(某些流程中会更早调用)。SetupPlayerInputComponent - 在UEnhancedInputComponent上使用旧版绑定:和
BindAction(FName,...)已被BindAxis,会导致编译错误。在= delete中设置DefaultInput.ini。DefaultInputComponentClass - 按钮按压触发Triggered:会在输入激活的每帧触发。单次按压使用
Triggered,释放使用Started。Completed - Ongoing状态下Completed不触发:如果任何触发器在当前帧报告,
Ongoing会被抑制。为清晰的按压/释放事件使用单独的操作。Completed - 游戏手柄摇杆未设置死区:摇杆会产生非零静止值。务必为每个摇杆映射添加。
DeadZone(Radial) - WASD转2D轴缺少SwizzleAxis:键盘产生一维输入。如果W/S没有,前后移动会停留在X轴,被Axis2D的向前移动忽略。
SwizzleAxis(YXZ) - 复制输入操作:输入是客户端本地的。复制操作结果(移动、技能激活),而非触发事件。
- 运行时使用MapKey/UnmapKey进行重映射:这些是编辑器/配置界面的辅助函数。使用子系统的玩家可映射按键API或切换上下文替代。
- 触发器类型与意图不符:需要时使用了
Hold,需要Down时使用了Started。根据交互模式匹配触发器类型:单次按压用Triggered,持续操作用Started,延迟激活用Triggered。Hold
Legacy Input Migration
旧版输入系统迁移
To migrate from the legacy input system to Enhanced Input: search for and calls and replace each with . Create a data asset for every old action name, choosing the appropriate (Boolean for buttons, Axis1D for single-axis, Axis2D for stick/WASD). Create a asset and add key mappings corresponding to the old / entries. Set in and enable the EnhancedInput plugin.
InputComponent->BindActionInputComponent->BindAxisUEnhancedInputComponent::BindActionUInputActionValueTypeUInputMappingContextDefaultInput.iniActionMappingsAxisMappingsDefaultInputComponentClassDefaultInput.ini要从旧版输入系统迁移到Enhanced Input:搜索和调用,将每个调用替换为。为每个旧操作名称创建数据资源,选择合适的(按钮用Boolean,单轴用Axis1D,摇杆/WASD用Axis2D)。创建资源,并添加与旧版中/条目对应的按键映射。在中设置并启用EnhancedInput插件。
InputComponent->BindActionInputComponent->BindAxisUEnhancedInputComponent::BindActionUInputActionValueTypeUInputMappingContextDefaultInput.iniActionMappingsAxisMappingsDefaultInput.iniDefaultInputComponentClassUI Input Mode
UI输入模式
Without CommonUI, manage input modes manually via :
APlayerController::SetInputMode()cpp
PC->SetInputMode(FInputModeUIOnly()); // cursor captured by UI, no game input
PC->SetInputMode(FInputModeGameAndUI()); // both UI and game receive input
PC->SetInputMode(FInputModeGameOnly()); // full game input, UI events suppressedCommonUI automates input routing through stacks and eliminates most manual calls — see .
UCommonActivatableWidgetSetInputModeue-ui-umg-slate如果未使用CommonUI,需通过手动管理输入模式:
APlayerController::SetInputMode()cpp
PC->SetInputMode(FInputModeUIOnly()); // 光标被UI捕获,无游戏输入
PC->SetInputMode(FInputModeGameAndUI()); // UI和游戏均可接收输入
PC->SetInputMode(FInputModeGameOnly()); // 完整游戏输入,UI事件被抑制CommonUI通过栈自动处理输入路由,可消除大多数手动调用 — 请参阅。
UCommonActivatableWidgetSetInputModeue-ui-umg-slateRelated Skills
相关技能
- — PlayerController input lifecycle,
ue-gameplay-framework/Possess,UnPossessSetupPlayerInputComponent - —
ue-ui-umg-slate/SetInputMode(FInputModeUIOnly()), cursor visibility, CommonUIFInputModeGameAndUI()stacksUCommonActivatableWidget - — binding Enhanced Input actions to GAS ability activation via input ID tags
ue-gameplay-abilities
- — PlayerController输入生命周期、
ue-gameplay-framework/Possess、UnPossessSetupPlayerInputComponent - —
ue-ui-umg-slate/SetInputMode(FInputModeUIOnly())、光标可见性、CommonUIFInputModeGameAndUI()栈UCommonActivatableWidget - — 通过输入ID标签将Enhanced Input操作绑定到GAS技能激活
ue-gameplay-abilities