天天看點

Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

下面的内容為 [中文直播]第39期 | 虎跳龍拿–新一代增強輸入架構EnhancedInput | Epic 大钊 的學習筆記,大量的内容來自視訊中的。

增強輸入系統(Enhanced Input System)是對預設輸入系統做了一個擴充,通過子產品化的方式,解耦了從輸入的按鍵配置到事件處理的邏輯處理過程,提供了更靈活、便利的輸入配置和處理功能,同時又能向後相容虛幻引擎4(UE4)中的預設輸入系統。

問題由來

目前的系統輸入的流程

Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

舊系統問題

  • 舊系統實作基礎的功能比較簡單,但在想建構更複雜機制上就得需要在User層做更多的工作。例如角色在不同情景下的輸入變化。(近戰/遠端/載具)
  • 過于簡陋,原來的輸入系統隻是告訴你事件,需自己實作衆多行為。例如按住/輕按兩下。

新系統目标

  • 重新梳理簡化。由原來的 Axis/Action 簡化為 Action
  • 運作時重映射輸入場景。UInputMappingContext
  • 對初級使用者易配置。大量預設行為實作,Tap/Hold…
  • 對進階使用者易擴充,可繼承子類擴充。
  • 修改器:修改輸入值
  • 觸發器:決定觸發條件
  • 優先級:配置輸入場景優先級
  • 子產品化,不再隻依賴ini配置,以資源asset方式配置,堆棧式分隔邏輯。
  • 提高性能,不需要檢查所有的輸入,隻需關心目前的場景和綁定。
  • UE5 正式替換掉舊有輸入系統

基礎用法

使用前的配置

在 Plugins 中,開啟 Enhanced Input 插件,并重新開機編輯器。

Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

在 Project Settings -> Input 分類中,替換預設類型(Default Classes)。原來的值可能為 UInputComponent,需要修改為 UEnhancedInputComponent。UEnhancedInputComponent 是 UInputComponent 的子類。

Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

項目中添加 “EnhancedInput” 子產品。可以在 PublicDependencyModuleNames 中添加,也可以在 PrivateDependencyModuleNames 中添加:

public class LeveForLight : ModuleRules
{
	public LeveForLight(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
	
		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });
                PrivateDependencyModuleNames.AddRange(new string[] { "EnhancedInput" });
	}
}
           

使用的大緻流程

下面為使用的大緻流程,具體的設定會在下面詳細介紹。

建立 InputAction

Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

建立 InputMapingContext

InputMapingContext 中記錄了按鍵和 Action 的綁定關系。一個按鍵和 action 是多對多的關系,即:一個按鍵可以和多個 Action 進行綁定,不同的按鍵可以綁定同一個 Action。

Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

綁定 Action 委托

綁定 Action 的委托。

藍圖方式如下:

Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

代碼方式如下:首先在類中定義了可以處理的 Action,然後在 SetupPlayerInputComponent 中進行綁定 Action 的回調方法。

UPROPERTY(EditDefaultsOnly, Category = "Input|Action")
	TObjectPtr<UInputAction> IA_LookUp;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	class UInputAction* JumpAction;
           
// Called to bind functionality to input
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
	{
		if (IA_LookUp)
		{
			EnhancedInputComponent->BindAction(IA_LookUp, ETriggerEvent::Triggered, this, &AMyCharacter::LookUp);
		}
	}
}

void AMyCharacter::LookUp(const FInputActionValue& InputValue)
{
}
           

應用 InputMappingContext

下面為在 Character 中,先擷取 PlayerController,再擷取 UEnhancedInputLocalPlayerSubsystem,最後應用 InputMappingContent 的過程。其中:

  • Priority:優先級,數字約大,優先級越高。

藍圖方式如下:

Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

代碼方式如下:現在類中定義需要處理 InputMappingContext,然後在 SetupPlayerInputComponent 進行綁定

UPROPERTY(EditDefaultsOnly, Category = Input)
TObjectPtr<UInputMappingContext> InputMappingContext;
           
#include "MyCharacter.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"

// Called to bind functionality to input
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	if (APlayerController* PC = CastChecked<APlayerController>(GetController()))
	{
		if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer()))
		{
			Subsystem->AddMappingContext(InputMappingContext, 100);
		}
	}
	if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
	{
		if (IA_LookUp)
		{
			EnhancedInputComponent->BindAction(IA_LookUp, ETriggerEvent::Triggered, this, &AMyCharacter::LookUp);
		}
	}
}

void AMyCharacter::LookUp(const FInputActionValue& InputValue)
{
}
           

UEnhancedInputComponent 是 UInputComponent 的子類。

另外:AddMappingContext 和 BindAction 的執行先後順序沒有限制,它是兩個獨立的過程

調試指令:ShowDebug enhancedinput,下面有更多的 Debug 指令。

核心概念

Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考
Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

EnhancedPlayerlnput

存儲按鍵映射:Key->InputAction

Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

InputModifier

修改器和觸發器可以在 Maping 和 InputAciton 中同時設定:

  • Mapping.Modifiers / Triggers 針對目前 IMC 場景,和按鍵強相關的
  • InputAction.Modifiers / Triggers 針對全局,不需要關心按鍵,主要關心值怎麼動,處理邏輯相關的,

兩個地方都可以配置 Triggers 和 Modifiers,上面兩個是鍊式處理的。先經過 Maping 再經過 Action。

Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

修改器有:

  • DeadZone: 限定值的範圍
  • Scalar:縮放一個标量
  • Negate:取反
  • Smooth:多幀之間平滑
  • CurveExponential:指數曲線,XYZ
  • CurveUser:自定義指數曲線,CurveFloat
  • FOVScaling: FOV縮放
  • ToWorldSpace:輸入裝置坐标系向世界坐标系轉換(調換XYZ順序)
  • SwizzleAxis:互換軸值
  • Collection: 嵌套子修改器集合
Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

比如:搖杆中的事件,為了防止誤觸,可以将較小的值限制為 0。

Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

InputTrigger

Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

  • ETriggerEvent:ETriggerState發生轉變時觸發的事件,BindXXX的時候關注某個事件
  • Down:值大于門檻值(預設0.5)就觸發
  • Pressed:不激活到激活
  • Released:激活到不激活
  • Hold:按住大于某個時間
  • HoldAndRelease:按住大于某個時間後松開
  • Tap: 按下後快速擡起(預設0.2)
  • Chorded: 根據别的Action關聯觸發
Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

InputAction

回調參數可以為:

  • FlnputActionValue:Action的值,XYZ,0/1。
  • FlnputActionlnstance:Action的運作時狀态。

在 C++ 中,回調方法可以為:

  • void()
  • vold(const FinputActionValue&)
  • void(const FinputActioninstance&)

在藍圖(BP)中:

  • void(FlnputActionValue ActionValue, float Elapsed Time, float TriggeredTime)
Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考
Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

Consume Input是否把事件吞噬掉,如果不吞噬的話,一個按鍵還是傳送到之後的事件處理流程。

Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

InputMappingContext

InputMappingContext 相當于一套目前的 Key->InputAction 的映射集合。多個IMC同時作用,高優先級的會先處理,如果沒有則觸發到低優先級的。高優先級的 Key 綁定會屏蔽低優先級的綁定。

Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

EnhancedInput 處理流程

  1. 相容 Input 處理
  2. 周遊 EnhancedActionMappings
  3. 通過 KeyStateMap 查詢擷取激活的 Action
  4. 應用 Mapping.Modifiers 修改值
  5. 應用 Mapping.Triggers 決定觸發狀态
  6. 應用 Action.Modifiers 修改值
  7. 應用 Action.Triggers 決定觸發狀态
  8. 周遊 InputStack 擷取 EnhancedInputComponent 中的 Binding 回調
  9. 觸發所有Delegates

注意:是先經過 Maping 修改,再經過 Action 修改。

Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考
Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

AddMappingContext 流程

  • InputMappingContext 會根據優先級排序
  • IMC:Mappings 也會根據動作關聯而優先級排序
  • IMC:Mappings 會複制添加到 Playerlnput 的 EnhancedActionMappings裡
Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

EnhancedInputSubsystem

Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

最佳實踐

IMC BindAction

  • 初始情況在應該在哪裡開始應用 IMC
  • 後續運作時在藍圖中應該如何切換 IMC
  • 何時 Remove IMC?
  • 在哪裡綁定 Action 和 Axis 在藍圖中如何 BindAction

PlayerController IMC+BindAction

  • C++ 中 SetupInputComponent 依然是最合适的位置
  • BP 中可在 BeginPlay 後 Add(IMC)
  • BP中可直接Add Action Event
Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考
Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

Pawn IMC+BindAction

  • C++ SetuplnputComponent依然合适
  • BP中應在Possessed事件内Add(IMC)
  • BP中可直接Add Action Event
Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考
Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

事件綁定的位置是解除安裝 Controller 中?還是 Pawn 上?

  • 和 Pawn 關聯的 action 寫在對應的 Pawn 上。
  • 基礎的操作可以寫在 controller 上

controller 控制的 Pawn 切換之後,會調用 Pawn 對應的 OnPossess 方法,繼而調用 SetupInputComponent 方法。

/** 
 * Called when this Pawn is possessed. Only called on the server (or in standalone).
 * @param NewController The controller possessing this pawn
 */
virtual void PossessedBy(AController* NewController);
           

Pawn Remove(IMC)

  • C++ UnPossessed 事件可移除自身 IMC
  • BP 可在 Unpossessed 事件來移除自身 IMC

另外:PlayerController 的 IMC 不需要移除,因為PC一直在

Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考

IMC BindAction最佳實踐

  • 分層的 IMC 設計:基本輸入(移動),武器/載具,行為/Buff
  • Add(IMC,Priority),規劃好 Priority 的值,IMC 的 Priorit 展現的是 Key 和 InputAction 之間的映射關系,但是找到 InputAction 之後,還是依然按照 InputStack 的順序來處理。
  • Pawn上可攜帶多個 IMC,但隻 Apply 一個
  • IMC 不一定跟 Pawn 綁定關聯,可根據運作時邏輯靈活Add
  • IMC 代表輸入的邏輯處理環境,BindAction 代表輸入事件該由誰來處理的職責

Debug

ConsoleCommands:

  • Input.+action ActionName Value:強制添加某個Action的輸入
  • Input.-action ActionName:移除某Action的輸入
  • Input.+key Key Value:添加某Key的輸入
  • Input.-key keyName:移除某 Key 的輸入
  • ShowDebug Enhancedlnput:顯示調試界面
Unreal Engine 增強輸入架構 EnhancedInput問題由來基礎用法核心概念EnhancedInputSubsystem最佳實踐參考
Playerlnput::InputKey/Axis{}

UEnhancedPlayerlnput:::InjectlnputForAction{}
           

擴充

  • 繼承擴充 InputModifier 和 InputTrigger,實作自己的輸入值鍊式修改邏輯,自己的觸發邏輯
  • 規劃好靈活的IMC應用政策,可繼承添加更多的資訊
  • 利用調試注入Key/Action可友善安排自己的測試輸入序列
  • EnhancedInput還在開發中,更多Todo改進

參考

  • UE5 – EnhancedInput(增強輸入系統)
  • [中文直播]第39期 | 虎跳龍拿–新一代增強輸入架構EnhancedInput | Epic 大钊

繼續閱讀