ue-input-system について
UE 5.8 の Enhanced Input 開発スキルです。入力アセット、C++ バインド、ランタイム設定に加え、トリガー、モディファイア、マッピングコンテキスト、キー再割り当て、入力モードフィルタリングを扱います。
主な機能
- 01Input Action と Mapping Context の設定
- 02C++ 入力イベントのバインドと解除
- 03トリガーイベントと標準トリガー
- 04入力モディファイアと軸変換
- 05コンテキスト優先度とランタイム再割り当て
活用シーン
- 01キャラクターアクションへのキーと入力イベントの割り当て
- 02長押し、タップ、連続タップ動作の設定
- 03スティックのデッドゾーン、感度、軸マッピングの調整
- 04ゲーム内キー再割り当て設定画面の作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ quodsoler/ unreal-engine-skills --skill ue-input-systemインストール後、Claude Code で/ue-input-systemを入力して読み込まれたか確認します。
同梱ファイルreferences/input-action-reference.md
詳細
UE Input System
対象エンジン:UE 5.8。以下の API は 5.8 のヘッダーに基づいて検証済みです。古い形式は「Deprecated — do not use」に記載しています。
Enhanced Input は、エンジンがサポートする唯一の入力経路です。EnhancedInput プラグイン(Engine/Plugins/EnhancedInput、5.8 ではデフォルトで有効)に含まれています。Build.cs の PublicDependencyModuleNames に "EnhancedInput" を追加してください。FKey/EKeys を直接扱う場合は "InputCore" も、入力モードのフィルタリングまたはユーザー設定の失敗理由コンテナを使用する場合は "GameplayTags" も追加します。ランタイムを構成するのは、UEnhancedPlayerInput、UEnhancedInputComponent、UEnhancedInputLocalPlayerSubsystem、データアセットの UInputAction/UInputMappingContext、およびプレイヤーのキー再割り当てに使用する UEnhancedInputUserSettings です。
Context
.agents/ue-project-context.md が存在する場合は読み込んでください(モジュール名、規約、有効なプラグイン、GAS/ネットワーク設定)。ファイルがなくても作業を中断しないでください。
リクエストとコードベースから対象領域を特定してください。異なるコードになる可能性のある解釈が 2 つある場合に限り、確認してください。
| リクエストの内容… | 参照先 |
|---|---|
| プラグイン、モジュール、ini の設定 | セットアップ |
| アクションとマッピングコンテキストの作成 | 入力アセット |
| C++ でのハンドラーのバインド | C++ でのアクションのバインド |
バインドするイベント(Started、Triggered、Completed) | トリガーイベント |
| 長押し、タップ、ダブルタップ、パルス、コード | 組み込みトリガー |
| デッドゾーン、感度、WASD→2D、Y 軸反転 | 組み込みモディファイアー |
| コンテキストの追加/削除、優先度、分割画面 | マッピングコンテキストと優先度 |
| ゲームプレイ状態によるコンテキストの有効化/無効化 | 入力モードのフィルタリング |
| プレイヤーのキー再割り当て、設定画面、保存 | ランタイムのキー再割り当て |
| PlayerController を持たないアクターでの入力 | PlayerController を使わない入力 |
| プラットフォームごとのマッピングコンテキストの切り替え | プラットフォームごとの入力データ |
| 新しいトリガーまたはモディファイアーの作成 | カスタムトリガー、カスタムモディファイアー |
| メニュー、カーソル、CommonUI | UI 入力モード |
| デバッグオーバーレイ | デバッグ |
クラスごとの詳細なパラメーターテーブルは、references/input-action-reference.md にあります。
Setup
// Build.cs
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput" });
DefaultInput.ini — エンジンのデフォルトクラスを Enhanced Input に設定します:
[/Script/Engine.InputSettings]
DefaultPlayerInputClass=/Script/EnhancedInput.EnhancedPlayerInput
DefaultInputComponentClass=/Script/EnhancedInput.EnhancedInputComponent
Enhanced Input のプロジェクト設定は UEnhancedInputDeveloperSettings(プロジェクト設定 → Engine → Enhanced Input)にあり、DefaultInput.ini の [/Script/EnhancedInput.EnhancedInputDeveloperSettings] に書き込まれます。C++ の動作を変更するキーは、bEnableUserSettings、UserSettingsClass、DefaultPlayerMappableKeyProfileClass、InputSettingsSaveSlotName、bEnableWorldSubsystem、DefaultWorldInputClass、bEnableInputModeFiltering、DefaultMappingContextInputModeQuery、DefaultInputMode、bEnableDefaultMappingContexts、bSendTriggeredEventsWhenInputIsFlushed です。
入力アセット
UInputAction : UDataAsset — 論理的なプレイヤーアクションごとに1つ作成します。C++の動作を変えるプロパティは次のとおりです。
| Property | Default | Meaning |
|---|---|---|
ValueType | EInputActionValueType::Boolean | Boolean、Axis1D(float)、Axis2D(FVector2D)、Axis3D(FVector) |
AccumulationBehavior | TakeHighestAbsoluteValue | または Cumulative。すべてのマッピングを合算するため、W + S は相殺されます |
bConsumeInput | true | 同じキーに対する優先度の低いEnhanced Inputマッピングをブロックします |
bConsumesActionAndAxisMappings | false | そのキーに対するレガシーのAction/Axisマッピングもブロックします |
bReserveAllMappings | false | 優先度の高いコンテキストによってマッピングが上書きされなくなります |
bTriggerWhenPaused | false | ゲームの一時停止中もアクションが発火します |
Triggers / Modifiers | empty | アクションレベルで適用され、マッピングごとの設定の後に処理されます |
PlayerMappableKeySettings | nullptr | UPlayerMappableKeySettings — アクションを再バインド可能にします |
UInputMappingContext : UDataAsset — キーとアクションのバインドをまとめて追加・削除します。
| Member | Notes |
|---|---|
DefaultKeyMappings | FInputMappingContextMappingData。GetMappings()で配列を読み取ります |
MappingProfileOverrides | TMap<FString, FInputMappingContextMappingData> — キープロファイルごとのオーバーライド |
RegistrationTrackingMode | Untracked(デフォルト)またはCountRegistrations |
InputModeFilterOptions | UseProjectDefaultQuery(デフォルト)、UseCustomQuery、DoNotFilter |
MapKey(Action, Key) / UnmapKey(Action, Key) | エディター/設定画面向けのヘルパーであり、実行時のリバインドAPIではありません |
HasMappingForInputAction(Action) | デフォルトのマッピングとプロファイルのオーバーライドを検索します |
各FEnhancedActionKeyMappingには、Action、Key、マッピングごとのTriggersとModifiers、SettingBehavior(EPlayerMappableKeySettingBehaviors:InheritSettingsFromAction、OverrideSettings、IgnoreSettings)、および省略可能なPlayerMappableKeySettingsのオーバーライドが含まれます。GetPlayerMappableKeySettings()とGetMappingName()で取得できます。
C++でのアクションのバインド
// MyCharacter.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "MyCharacter.generated.h"
class UInputAction;
class UInputMappingContext;
struct FInputActionValue;
UCLASS()
class MYGAME_API AMyCharacter : public ACharacter
{
GENERATED_BODY()
public:
virtual void BeginPlay() override;
virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override;
protected:
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();
};
// MyCharacter.cpp
#include "MyCharacter.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "InputActionValue.h"
#include "Engine/LocalPlayer.h"
#include "GameFramework/PlayerController.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();
APlayerController* PC = Cast<APlayerController>(GetController());
if (UEnhancedInputLocalPlayerSubsystem* Subsystem =
ULocalPlayer::GetSubsystemFromController<UEnhancedInputLocalPlayerSubsystem>(PC))
{
Subsystem->AddMappingContext(DefaultMappingContext, 0);
}
}
void AMyCharacter::Move(const FInputActionValue& Value)
{
const FVector2D Axis = Value.Get<FVector2D>();
AddMovementInput(GetActorForwardVector(), Axis.Y);
AddMovementInput(GetActorRightVector(), Axis.X);
}
void AMyCharacter::StartJump() { Jump(); }
void AMyCharacter::StopJump() { StopJumping(); }
ハンドラーのシグネチャ
UEnhancedInputComponent::BindActionはFEnhancedInputActionEventBinding&を返し、3種類のネイティブデリゲートのいずれかに一致するメンバー関数、または名前で指定するUFUNCTIONを受け取ります。
| Signature | Handler |
|---|---|
FEnhancedInputActionHandlerSignature | void Handler() |
FEnhancedInputActionHandlerValueSignature | void Handler(const FInputActionValue& Value) |
FEnhancedInputActionHandlerInstanceSignature | void Handler(const FInputActionInstance& Instance) |
FEnhancedInputActionHandlerDynamicSignature | BindAction(Action, Event, Object, FName("OnFirePressed")) |
FInputActionInstanceは、GetValue()、GetTriggerEvent()、GetElapsedTime()(Started + Ongoing + Triggered)、GetTriggeredTime()(Triggeredのみ)、GetLastTriggeredWorldTime()、GetTriggers()、GetModifiers()、GetSourceAction()を公開します。
ラムダとポーリング可能な値:
EIC->BindActionValueLambda(InteractAction, ETriggerEvent::Triggered,
[this](const FInputActionValue& Value) { TryInteract(Value.Get<bool>()); });
EIC->BindActionInstanceLambda(ChargeAction, ETriggerEvent::Ongoing,
[this](const FInputActionInstance& Instance) { SetChargeProgress(Instance.GetElapsedTime()); });
// No delegate — just reflects the current value, poll it from Tick
FEnhancedInputActionValueBinding& LookBinding = EIC->BindActionValue(LookAction);
const FVector2D LookAxis = LookBinding.GetValue().Get<FVector2D>();
バインドの解除:
FEnhancedInputActionEventBinding& Binding =
EIC->BindAction(JumpAction, ETriggerEvent::Started, this, &AMyCharacter::StartJump);
const uint32 BindingHandle = Binding.GetHandle(); // uint32, EnhancedInputComponent.h:165
EIC->RemoveBindingByHandle(BindingHandle); // one binding, later
EIC->ClearBindingsForObject(this); // every binding owned by this object; ClearActionBindings() drops all
トリガーイベント
ETriggerEventは、このティックで発生したトリガー状態の遷移を表すビットマスク(ENUM_CLASS_FLAGS)です。
| Event | Bit | State transition | Bind it for |
|---|---|---|---|
Triggered | 1 << 0 | None→Triggered、Ongoing→Triggered、Triggered→Triggered | アクティブなすべてのフレーム。連続的な移動 |
Started | 1 << 1 | None→Ongoing、None→Triggered | 評価の最初のフレーム。一度だけの押下アクション |
Ongoing | 1 << 2 | Ongoing→Ongoing | 押し続けているが、まだトリガーされていない状態(チャージ中) |
Canceled | 1 << 3 | Ongoing→None | トリガー条件を満たす前に離した場合 |
Completed | 1 << 4 | Triggered→None | トリガー後に離した場合。連続アクションを停止します |
同じティックで両方が発生する場合、Startedは必ずTriggeredより先に発火します。アクションのいずれかのトリガーがOngoingを報告するティックでは、Completedは発火しません。押下と解放の両方を確実に検出する必要がある場合は、2つのアクションに分けてください。
組み込みトリガー
クラスごとのプロパティとデフォルト値については、references/input-action-reference.mdを参照してください。
| クラス | 表示名 | 動作 |
|---|---|---|
UInputTriggerDown | 押下 | 値が作動しているフレームごとに発火します(アクションにトリガーがない場合の暗黙的なデフォルト) |
UInputTriggerPressed | 押したとき | 最初に作動したときに一度だけ発火します。押し続けても繰り返しません |
UInputTriggerReleased | 離したとき | 作動後、値がActuationThresholdを下回ったときに一度だけ発火します |
UInputTriggerHold | 長押し | HoldTimeThreshold秒経過後に発火します。bIsOneShot = falseの場合は発火し続けます |
UInputTriggerHoldAndRelease | 長押しして離したとき | HoldTimeThreshold以上押し続けた場合、離したときに発火します |
UInputTriggerTap | タップ | TapReleaseTimeThreshold以内に離したときに発火します |
UInputTriggerRepeatedTap | 連続タップ | NumberOfTapsWhichTriggerRepeat回タップし、各タップの間隔がRepeatDelay未満の場合に発火します |
UInputTriggerPulse | パルス | 押し続けている間、Interval秒ごとに発火します。発火回数はTriggerLimitが上限となります |
UInputTriggerChordAction | コードアクション | ChordActionがトリガーされている間のみ発火し、同じキーの優先度が低いマッピングにUInputTriggerChordBlockerを挿入します |
ETriggerTypeは、同じアクション上のトリガーをどのように組み合わせるかを決定します。Explicit(少なくとも1つが発火する必要があります)、Implicit(すべてが発火する必要があります)、Blocker(IsBlockingがtrueを返す間、すべてをブロックします)。ETriggerEventsSupported(None、Instant、Uninterruptible、Ongoing、All)は、トリガーが生成できるETriggerEventを宣言します。
組み込みモディファイア
マッピングごとのモディファイアが最初に実行され、その後、アクションレベルのModifiers配列が実行されます。各グループ内では配列の順序で実行されます。
| クラス | 表示名 | 効果 |
|---|---|---|
UInputModifierDeadZone | デッドゾーン | LowerThreshold未満をゼロにし、UpperThresholdで1にリマップします。TypeはAxial、Radial、UnscaledRadialです |
UInputModifierScalar | スカラー | 各軸にFVector Scalarを乗算します |
UInputModifierScaleByDeltaTime | デルタタイムによるスケーリング | フレームのDeltaTimeを乗算します |
UInputModifierNegate | 符号反転 | bX/bY/bZで選択した軸の符号を反転します |
UInputModifierSwizzleAxis | 入力軸の値を並べ替え | 軸を並べ替えます。OrderのデフォルトはEInputAxisSwizzle::YXZです |
UInputModifierSmooth | 平滑化 | 直近のサンプルの移動平均を計算します |
UInputModifierSmoothDelta | デルタを平滑化 | 平滑化された正規化デルタです。SmoothingMethod、Speed、EasingExponentを使用します |
UInputModifierResponseCurveExponential | 応答曲線 - 指数関数 | 軸ごとにsign(x) * pow(abs(x), CurveExponent)を適用します |
UInputModifierResponseCurveUser | 応答曲線 - ユーザー定義 | 軸ごとに1つのUCurveFloatを使用します |
UInputModifierFOVScaling | FOVスケーリング | ズーム中も角速度を一定に保つため、カメラのFOVに応じてスケーリングします |
UInputModifierToWorldSpace | ワールド空間に変換 | 2D軸をワールド空間に変換します |
WASD → Axis2D(アクションのAccumulationBehavior = Cumulative):
W:Swizzle Input Axis Values (YXZ)→ Y = +1S:Swizzle Input Axis Values (YXZ)+Negate (bY)→ Y = −1D:なし → X = +1A:Negate (bX)→ X = −1
ゲームパッドのスティック:各スティックのマッピングにDead Zone (Radial, LowerThreshold = 0.2)を設定します。
マウスルック:マッピングにScalar(0.4, 0.4, 1.0)、次にSmooth、続けてFOV Scalingを設定します。
コンテキストのマッピングと優先度
Subsystem->AddMappingContext(GameplayContext, 0); // higher integer = higher priority
Subsystem->AddMappingContext(VehicleContext, 1);
FModifyContextOptions Options;
Options.bForceImmediately = true; // rebuild now instead of at end of frame
Options.bNotifyUserSettings = true; // register these mappings with UEnhancedInputUserSettings
Subsystem->AddMappingContext(MenuContext, 2, Options);
Subsystem->RemoveMappingContext(VehicleContext);
Subsystem->ClearAllMappings();
int32 FoundPriority = 0;
const bool bActive = Subsystem->HasMappingContext(GameplayContext, FoundPriority);
const FInputActionValue Current = Subsystem->GetPlayerInput()->GetActionValue(MoveAction);
FModifyContextOptions のデフォルト値は、bIgnoreAllPressedKeysUntilRelease = true、bForceImmediately = false、bNotifyUserSettings = false です。最初の設定によって、コンテキストの切り替え時に押されたままのキーから発生するゴースト入力はすでに抑制されています。オプトインだと考えて明示的に設定しないでください。押されたままのキーを新しいコンテキストに引き継ぐ場合に限り、false に設定します。
UInputAction の bConsumeInput = true(デフォルト)を設定すると、優先度の高いコンテキストで同じ物理キーがマッピングされている場合、そのキーに対応する優先度の低いバインディングがすべてブロックされます。優先度と bConsumeInput を使ってモードを分離します。たとえば、乗り物用コンテキストで Spacebar の入力を消費すると、運転中にキャラクターの Jump アクションが実行されなくなります。
IMC の RegistrationTrackingMode は、Untracked(追加回数にかかわらず、最初の RemoveMappingContext で削除されます)または CountRegistrations(追加と同じ回数だけ削除されるまで適用されたままになります。複数のシステムで IMC を共有する場合に使用します)です。
各ローカルプレイヤーは個別の UEnhancedInputLocalPlayerSubsystem を所有するため、分割画面のコンテキストがプレイヤー間で漏れることはありません。特定のプレイヤーのサブシステムは、ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(LocalPlayer) または ULocalPlayer::GetSubsystemFromController<UEnhancedInputLocalPlayerSubsystem>(PlayerController) で取得します。デバイスなしで入力をシミュレートするには、InjectInputForAction(Action, RawValue, Modifiers, Triggers) または InjectInputVectorForAction(Action, Value, Modifiers, Triggers) を使用します。
入力モードのフィルタリング
コンテキストを追加・削除する代わりに、ゲームプレイタグの状態に基づいてマッピングコンテキスト全体を制御します。UEnhancedInputDeveloperSettings で bEnableInputModeFiltering を有効にする必要があります。
- サブシステムは現在のモードを保持します。
GetInputMode()、SetInputMode(Tags, Options)、AppendTagsToInputMode、AddTagToInputMode、RemoveTagsFromInputMode、RemoveTagFromInputModeがあり、いずれも省略可能なFModifyContextOptionsを受け取ります。 - 各
UInputMappingContextはInputModeFilterOptionsでマッチング方法を選択します。UseProjectDefaultQuery(プロジェクトのDefaultMappingContextInputModeQuery)、UseCustomQuery(IMC 独自のInputModeQueryOverride)、またはDoNotFilterです。 UEnhancedInputDeveloperSettings::DefaultInputModeは、新しいUEnhancedPlayerInputごとにモードを初期設定します。- クエリに一致しないコンテキストは登録されたまま入力を生成しなくなるため、優先度や登録数は変わりません。
Subsystem->SetInputMode(FGameplayTagContainer(MyGameplayTags::TAG_InputMode_Menu));
実行時のキーの再バインド
UEnhancedInputUserSettings(UserSettings/EnhancedInputUserSettings.h)が、正式にサポートされている再バインド方法です。これは USaveGame であり、bEnableUserSettings が有効な場合にサブシステムごとに作成され、InputSettingsSaveSlotName で指定されたスロットに保存されます。
#include "EnhancedInputSubsystems.h"
#include "UserSettings/EnhancedInputUserSettings.h"
void UMyRebindWidget::RebindKey(FName MappingName, const FKey& NewKey)
{
UEnhancedInputLocalPlayerSubsystem* Subsystem =
ULocalPlayer::GetSubsystemFromController<UEnhancedInputLocalPlayerSubsystem>(GetOwningPlayer());
UEnhancedInputUserSettings* Settings = Subsystem ? Subsystem->GetUserSettings() : nullptr;
if (!Settings)
{
return;
}
FMapPlayerKeyArgs Args;
Args.MappingName = MappingName;
Args.Slot = EPlayerMappableKeySlot::First;
Args.NewKey = NewKey;
FGameplayTagContainer FailureReason;
Settings->MapPlayerKey(Args, FailureReason);
if (FailureReason.IsEmpty())
{
Settings->SaveSettings();
}
}
設定 UI に表示する必要がある IMC は、サブシステムに一度も追加されていないものも含めて、RegisterInputMappingContext(IMC) で登録します。bNotifyUserSettings = true を指定してコンテキストを追加した場合は、自動的に登録されます。マッピングを取得するには FindMappingsInRow(MappingName) と FindCurrentMappingForSlot(MappingName, Slot)、リセットするには ResetAllPlayerKeysInRow または ResetKeyProfileIdToDefault、保存するには SaveSettings() / AsyncSaveSettings() を使用します。プロファイル識別子は FGameplayTag ではなく FString です。ProfileIdString、GetProfileIdString()、GetActiveKeyProfileId()、GetKeyProfileWithId()、SetActiveKeyProfile() を使用します。
アクションまたはマッピングを再バインド可能にするには、UPlayerMappableKeySettings(Name、DisplayName、DisplayCategory、Metadata、SupportedKeyProfileIds)を設定する必要があります。これは UInputAction に設定するか、SettingBehavior = OverrideSettings として FEnhancedActionKeyMapping に設定します。API と構造体の全一覧については、references/input-action-reference.md を参照してください。
PlayerController を使用しない入力
UEnhancedInputWorldSubsystem(5.8 で試験的に導入)を使うと、所有されることのないアクターでも入力デリゲートを受け取れるようになります。UEnhancedInputDeveloperSettings の bEnableWorldSubsystem で有効にしてください。
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "Engine/World.h"
void AMyDoor::BeginPlay()
{
Super::BeginPlay();
// AddActorInputComponent reads AActor::InputComponent, created only for possessed actors.
if (!InputComponent)
{
InputComponent = NewObject<UEnhancedInputComponent>(this, TEXT("DoorInputComponent"));
InputComponent->RegisterComponent();
}
UEnhancedInputComponent* EIC = CastChecked<UEnhancedInputComponent>(InputComponent);
EIC->BindAction(OpenAction, ETriggerEvent::Started, this, &AMyDoor::Open);
if (UEnhancedInputWorldSubsystem* WorldInput =
GetWorld()->GetSubsystem<UEnhancedInputWorldSubsystem>())
{
WorldInput->AddActorInputComponent(this);
WorldInput->AddMappingContext(DoorContext, 0);
}
}
AddActorInputComponent を呼び出すたびに、EndPlay で RemoveActorInputComponent も呼び出してください。このサブシステムはローカルプレイヤー用のものと同じ IEnhancedInputSubsystemInterface を実装しているため、AddMappingContext や InjectInputForAction などの動作は同じです。ただし、ユーザー設定もローカルプレイヤーもありません。
プラットフォームごとの入力データ
UEnhancedInputPlatformSettings(UPlatformSettings、UEnhancedInputPlatformSettings::Get())には、UEnhancedInputPlatformData のサブクラスを格納する InputData 配列があります。各サブクラスでは、特定のプラットフォームである UInputMappingContext を別のものに差し替える TMap の MappingContextRedirects を定義します。GetContextRedirect(Context) は置換先を返し、置換先がなければ元のコンテキストを返します。ゲームプレイコードで分岐することなく、タッチ用またはコンソール用のコンテキストに差し替える場合に使用してください。Get() の呼び出しには Build.cs に DeveloperSettings が必要です(インラインで UPlatformSettingsManager を呼び出します)。
カスタムトリガー
UInputTrigger をサブクラス化し、UpdateState_Implementation をオーバーライドして、ETriggerState::None、Ongoing、または Triggered を返します。
// MyDoubleClickTrigger.h
#pragma once
#include "EnhancedPlayerInput.h"
#include "Engine/World.h"
#include "InputTriggers.h"
#include "MyDoubleClickTrigger.generated.h"
UCLASS(EditInlineNew, meta = (DisplayName = "Double Click"))
class MYGAME_API UMyDoubleClickTrigger : 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
{
const bool bActuated = IsActuated(ModifiedValue);
const float Now = PlayerInput->GetWorld()->GetTimeSeconds();
ETriggerState Result = ETriggerState::None;
if (bActuated && !bWasActuated)
{
if ((Now - LastPressTime) <= DoubleClickThreshold)
{
LastPressTime = 0.f;
Result = ETriggerState::Triggered;
}
else
{
LastPressTime = Now;
}
}
bWasActuated = bActuated;
return Result;
}
private:
float LastPressTime = 0.f;
bool bWasActuated = false;
};
IsActuated(Value) は Value.GetMagnitudeSq() >= ActuationThreshold * ActuationThreshold です。時間ベースのトリガーには UInputTriggerTimedBase を派生元として使用してください。このクラスは、入力が作動すると Ongoing に遷移し、HeldDuration、CalculateHeldDuration(PlayerInput, DeltaTime)、および bAffectedByTimeDilation を利用できます。ブロッカーの場合は IsBlocking(const ETriggerState State) const を、デバッグ HUD の場合は GetDebugState() const をオーバーライドしてください。トリガーがマッピングの再構築をまたいで状態を保持する場合は、ReceiveTriggerReinstanced_Implementation(const UInputTrigger* OldTrigger) をオーバーライドして Super を呼び出してください。
カスタムモディファイアー
UInputModifier をサブクラス化し、次の関数をオーバーライドします。
virtual FInputActionValue ModifyRaw_Implementation(
const UEnhancedPlayerInput* PlayerInput, FInputActionValue CurrentValue, float DeltaTime) override;
返された値は、後続の処理に進む前にアクションの ValueType に戻されるため、内部では任意の形状を返せます。FInputActionValue(CurrentValue.GetValueType(), Vector) を使うと、その形状を維持できます。デバッグオーバーレイの色を制御するには、GetVisualizationColor_Implementation(FInputActionValue SampleValue, FInputActionValue FinalValue) const をオーバーライドしてください。実例:references/input-action-reference.md。
UI 入力モード
CommonUI を使用しない場合は、PlayerController で SetInputMode(FInputModeUIOnly())、SetInputMode(FInputModeGameAndUI())、または SetInputMode(FInputModeGameOnly()) を使ってモードを切り替えます。
CommonUI では入力が UCommonActivatableWidget のスタック経由でルーティングされるため、手動で SetInputMode を呼び出す場面がほとんどなくなります。Enhanced Input と Common Input は統合されています。UCommonInputSettings::bEnableEnhancedInputSupport(プロジェクト設定 → ゲーム → Common Input。再起動が必要)を有効にすると、CommonUI のクリックアクションと戻るアクションがデータテーブルの行ではなく、UInputAction アセット(UCommonUIInputData::EnhancedInputClickAction と EnhancedInputBackAction)になります。ウィジェットスタック、アクティベート可能なウィジェット、入力設定については ue-ui-umg-slate を参照してください。
デバッグ
ShowDebug EnhancedInput は、適用されたマッピングコンテキスト、各アクションの値とトリガー状態、および各トリガーの GetDebugState() を出力します。ShowDebug WorldSubsystemInput は UEnhancedInputWorldSubsystem について同様の情報を出力します。ShowDebug InputSettings は開発者設定を出力します。VeryVerbose レベルの LogWorldSubsystemInput は、ワールドサブシステムが処理するすべてのキーをログに記録します。
非推奨 — 使用しないでください
| 出力しないでください | 5.8 で使用 | ソース |
|---|---|---|
UInputTriggerCombo | 置き換えなし — UInputTriggerChordAction、タイマー、またはステートマシンを使ってシーケンスを構築してください | InputTriggers.h:571 の UE_DEPRECATED(5.8) |
FInputComboStepData, FInputCancelAction | 置き換えなし | InputTriggers.h:530,551 の UE_DEPRECATED(5.8) |
FEnhancedInputKeys::ComboKey | 置き換えなし | EnhancedInputModule.h:20 の UE_DEPRECATED(5.8) |
UInputMappingContext::Mappings | DefaultKeyMappings / GetMappings() | InputMappingContext.h:93 の UE_DEPRECATED(5.7) |
UEnhancedInputPlatformSettings::LoadInputDataClasses(), InputDataClasses | GetInputData() / ForEachInputData() | EnhancedInputPlatformSettings.h:77,88 の UE_DEPRECATED(5.7) |
UEnhancedPlayerInput::GetAppliedInputContexts() | GetAppliedInputContextData() | EnhancedPlayerInput.h:175 の UE_DEPRECATED(5.6) |
FMapPlayerKeyArgs::ProfileId (FGameplayTag), SetKeyProfile(FGameplayTag), GetCurrentKeyProfile(), GetCurrentKeyProfileIdentifier(), GetAllSavedKeyProfiles(), GetKeyProfileWithIdentifier(), ResetKeyProfileToDefault(FGameplayTag), GetProfileIdentifer() | ProfileIdString (FString), SetActiveKeyProfile(FString), GetActiveKeyProfile(), GetActiveKeyProfileId(), GetAllAvailableKeyProfiles(), GetKeyProfileWithId(), ResetKeyProfileIdToDefault(FString), GetProfileIdString() | UserSettings/EnhancedInputUserSettings.h:86,706,730,722,754,776,673,327 の UE_DEPRECATED(5.6) |
UPlayerMappableKeySettings::SupportedKeyProfiles | SupportedKeyProfileIds (TArray<FString>) | PlayerMappableKeySettings.h:62 の UE_DEPRECATED(5.6) |
UEnhancedInputDeveloperSettings::bShouldLogAllWorldSubsystemInputs | VeryVerbose の LogWorldSubsystemInput | EnhancedInputDeveloperSettings.h:150 の UE_DEPRECATED(5.6) |
UPlayerMappableInputConfig | UEnhancedInputUserSettings | PlayerMappableInputConfig.h:23 の UE_DEPRECATED(5.3) |
UInputComponent::BindAxis, BindAction(FName, EInputEvent, Object, Func), BindAxisKey, BindVectorAxis, BindKey, BindTouch, BindGesture | UEnhancedInputComponent::BindAction(UInputAction*, ETriggerEvent, Object, Func) | UEnhancedInputComponent で = delete、EnhancedInputComponent.h:613-634 |
よくある間違い
SetupPlayerInputComponent でマッピングコンテキストを追加する: この呼び出しは、コントローラーとローカルプレイヤーが解決される前に実行される場合があります。コンテキストは BeginPlay、OnPossess/PossessedBy、または PlayerControllerChanged ハンドラーで追加してください。
「念のため」bIgnoreAllPressedKeysUntilRelease = true に設定する: FModifyContextOptions ではすでにデフォルト値です。false に設定する場合にのみ変更してください。
ボタンの押下に Triggered をバインドする: Triggered はアクティブなフレームごとに発生します。押下時に一度だけ実行するには Started を、離したときには Completed を使用してください。
Ongoing と同時に Completed が発生すると期待する: トリガーが Ongoing を報告するティックでは、Completed は抑制されます。それぞれに独自のトリガーを持つ2つのアクションに分けてください。
スティックにデッドゾーンがない: アナログスティックはゼロ以外の値で静止します。すべてのスティックマッピングに Dead Zone (Radial) を追加してください。
WASD のスウィズル設定がない: キーボードキーは X 軸に1D値を出力します。W と S に Swizzle Input Axis Values (YXZ) を設定しないと、前後の入力が Axis2D アクションの Y 成分に届きません。
プレイヤーのキー再割り当てに MapKey/UnmapKey を呼び出す: これらは IMC アセットを変更するもので、エディターや設定向けのヘルパーです。代わりに UEnhancedInputUserSettings::MapPlayerKey を使用してください。また、キー再割り当て UI に表示するコンテキストを追加するときは、bNotifyUserSettings = true を渡してください。
トリガーイベントをレプリケートする: 入力はクライアントローカルです。レプリケートするのは結果(移動入力、アビリティの起動など)であり、ETriggerEvent はレプリケートしないでください。
UEnhancedInputComponent でレガシーバインドを使用する: BindAxis と FName の BindAction オーバーロードは = delete であり、コンパイルに失敗します。ENHANCED_INPUT_ALLOW_LEGACY_BINDING=1 を定義するのではなく、移行してください。
関連スキル
ue-gameplay-framework—APlayerController、ポゼッション、SetupPlayerInputComponentのライフサイクルue-ui-umg-slate— CommonUI のアクティベート可能なウィジェットスタック、入力設定、カーソルとフォーカスue-character-movement—AddMovementInputを通じたFInputActionValueの消費ue-gameplay-abilities— 入力からのアビリティの有効化、UAbilitySystemComponentの入力 IDue-actor-component-architecture—UActorComponent/UInputComponentの所有権、EnableInput、コンポーネントが所有する入力- こちらも関連します:
ue-cpp-foundations、ue-game-features、ue-gameplay-cameras、ue-mover