UE5 提供了一種對複雜輸入處理或運行時重新映射按鍵增强輸入插件。此插件向上兼容UE4的默認輸入系統,并可以實現径向死区、同时按键、上下文输入和优先级安排等多種功能。
核心概念:
(1)Input Actions:
Input Action 代表角色需要做出的任意動作,例如跳躍或攻擊等等。同時還可以代表輸入的狀態,例如按鍵按下時保持衝刺狀態。
(2)Input Mapping Contexts
Input Mapping Context将用户输入映射到输入动作,并可以动态地为每个用户添加、移除或安排优先次序。一下是UE的官方文檔介紹。
输入映射上下文(Input Mapping Context)描述一个或多个输入动作的触发规则。输入映射上下文的基本结构是一个层级结构,最上层包含一组输入动作。在输入动作层下面,是可以触发各个输入动作的用户输入,例如按键、按钮和方向轴。
底层包含各个用户输入的输入触发器和输入修饰器列表,可用于确定如何筛选或处理输入的原始值,以及它必须满足哪些限制才能驱动顶层的输入动作。
输入可以有多个输入修饰器和输入触发器。这些修饰器和触发器会按照其在列表中的顺序被计算;这对于输入修饰器尤其重要,因为修饰器将使用每个步骤的输出作为下个步骤的输入。
(3)Modifiers
Modifiers 用于修改来自用户设备的原始输入值。例如negate修改器可以改變輸入值1成爲-1.
输入修饰器是一种预处理器,能够修改UE5接收到的原始输入值,然后再将其发送给输入触发器(Input Trigger)。增强输入插件随附多种输入修饰器,可以执行各种任务,例如更改轴顺序、实现"死区"、将轴输入转换为世界空间以及其他功能。
在输入映射上下文中,每个与输入动作关联的输入,都会经历用户定义的一系列输入修饰器,然后再进入该输入的输入触发器。输入修饰器会按照其顺序依次应用,每个输入修饰器的输出值都会成为下一个修饰器的输入值。
你可以選擇使用UE提供的一系列修改器例如Negate, DeadZone 和 Swizzle Input Axis Value。也可以添加自己的modifier。
(4)Triggers
使用经过修饰器修改的输入值,或者使用其他输入动作的输出值,来确定是否激活输入动作。输入映射上下文中的输入动作,其每个输入都可以有一个或多个触发器。例如,拍摄照片时,可能需要用户按住鼠标左键约0.25秒,同时,还有一个用于控制摄像机拍照方向的输入动作处于激活状态。
使用方法:
(1)启用插件:
在编辑器中打开 编辑(Edit) 下拉菜单并选择 插件(Plugins),即可启用此插件。在插件列表的 输入(Input) 分段中,找到并启用增强输入插件,然后重启编辑器。
(2)添加(Input Actions):
我們可以在UE Content/ThirdPerson/Input/Actions 文件夾下(單擊鼠標右鍵->Input->Input Action)。
在雙擊打開創建的(Input Actions)之後,可以通過設置(Value Type)來選擇一種返回的輸入值。(例如:跳躍action選擇對應默認的bool,而移動action涉及多個方向,則使用Axis2D)
(3)添加(Input Mapping Context):
我們可以在UE Content/ThirdPerson/Input 文件夾下(單擊鼠標右鍵->Input->Input Mapping Context)。雙擊可以綁定相應的Action到按鍵。圖片提供了移動Action和衝刺Action兩個例子。
(4)C++ 添加Action和Action Mapping Context到character:
// ProjectDCharacter .h
UCLASS(config=Game)
class AProjectDCharacter : public ACharacter
{
GENERATED_BODY()
/** Player controller reference */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = PlayerController, meta = (AllowPrivateAccess = "true"))
APlayerController* PlayerController;
/** Move Input Action */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
UInputAction* MoveAction;
protected:
// APawn interface
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
// To add mapping context
virtual void BeginPlay();
/** Called for movement input */
void Move(const FInputActionValue& Value);
}
// ProjectDCharacter .cpp
void AProjectDCharacter::BeginPlay()
{
// Call the base class
Super::BeginPlay();
PlayerController = Cast<APlayerController>(Controller);
if (PlayerController)
{
//Add Input Mapping Context
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
{
Subsystem->AddMappingContext(DefaultMappingContext, 0);
}
}
}
// Input binding
void AProjectDCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
// Set up action bindings
if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent)) {
// Moving
EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AProjectDCharacter::Move);
}
else
{
UE_LOG(LogTemplateCharacter, Error, TEXT("'%s' Failed to find an Enhanced Input component! This template is built to use the Enhanced Input system. If you intend to use the legacy system, then you will need to update this C++ file."), *GetNameSafe(this));
}
}
void AProjectDCharacter::Move(const FInputActionValue& Value)
{
// input is a Vector2D
FVector2D MovementVector = Value.Get<FVector2D>();
if (Controller != nullptr)
{
const FVector ForwardDirection = FVector(0.0, 1.0, 0.0);
const FVector RightDirection = FVector(1.0, 0.0, 0.0);
AddMovementInput(ForwardDirection, MovementVector.X);
AddMovementInput(RightDirection, MovementVector.Y);
}
}
(5) 綁定到CharacterBlueprint:
由於我使用的是UE創建的Thirdperson C++項目模板,我的character是有默認的藍圖的,因此只需要在藍圖中添加Input Action 指向的實例。