虚幻5新特性之EnhancedInput

本文详细介绍了如何在虚幻5中利用EnhancedInput插件扩展原生输入系统,包括快速准备、调整第三人称模板输入配置,以及利用Action和ActionContext进行高级输入操作。通过新框架,支持点触和持续按下等特性,提升游戏交互体验。

提要

本文是对虚幻5新特性插件Enhanced Input的使用学习和代码框架解读,将会从应用和底层两方面对该系统进行分析。

Enhanced Input是对虚幻原生Input系统的拓展,其对输入的处理思路和原Input系统在流程上的思路是一致的。所不同的在于,对一些核心概念进行了提取和抽象,如Action和Action Context。不仅如此,在新框架的加持下,更多的功能特性可以得到发挥,如点触和持续按下等触发操作等。

快速使用

准备工作

Enhanced Input是以内置插件的形式提供,在Plugins面板,勾选并重启引擎即可激活:

在这里插入图片描述

在ContentBrowser里右键,可以看到已经出现了Input相关的新的条目,主要是InputAction资产和InputMapContext资产,说明插件激活成功。

在这里插入图片描述

然后需要到项目设置里的Input分栏里,修改默认类的设置:

在这里插入图片描述

随后,在代码层面需要在项目的Build.cs文件中添加相应的依赖模块:

public class InsideEnhancedInput : ModuleRules
{
	public InsideEnhancedInput(ReadOnlyTargetRules Target) : base(Target)
	{
		...
		
		PrivateDependencyModuleNames.AddRange(new string[] {"EnhancedInput"});
	}
}

这样,不论在Editor里还是项目代码里,我们都可以自由的使用Enhanced Input相关内容了。

修改第三人称模板的输入

原第三人称模板的输入配置介绍

第三人称模板的输入的初识设置主要还是通过在Input->Bindings界面将输入的字符串和按键进行绑定,再在代码/蓝图中为动作(使用字符串)绑定好相应的回调事件。

在这里插入图片描述

相应的输入绑定代码:

//////////////////////////////////////////////////////////////////////////
// Input

void AInsideEnhancedInputCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
{
	// Set up gameplay key bindings
	check(PlayerInputComponent);
	PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
	PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);

	PlayerInputComponent->BindAxis("Move Forward / Backward", this, &AInsideEnhancedInputCharacter::MoveForward);
	PlayerInputComponent->BindAxis("Move Right / Left", this, &AInsideEnhancedInputCharacter::MoveRight);

	// We have 2 versions of the rotation bindings to handle different kinds of devices differently
	// "turn" handles devices that provide an absolute delta, such as a mouse.
	// "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick
	PlayerInputComponent->BindAxis("Turn Right / Left Mouse", this, &APawn::AddControllerYawInput);
	PlayerInputComponent->BindAxis("Turn Right / Left Gamepad", this, &AInsideEnhancedInputCharacter::TurnAtRate);
	PlayerInputComponent->BindAxis("Look Up / Down Mouse", this, &APawn::AddControllerPitchInput);
	PlayerInputComponent->BindAxis("Look Up / Down Gamepad", this, &AInsideEnhancedInputCharacter::LookUpAtRate);

	// handle touch devices
	PlayerInputComponent->BindTouch(IE_Pressed, this, &AInsideEnhancedInputCharacter::TouchStarted);
	PlayerInputComponent->BindTouch(IE_Released, this, &AInsideEnhancedInputCharacter::TouchStopped);
}
使用EnhancedInput调整第三人称模板

首先创建输入相关的资产,包括5个InputAction:

  • IA_MoveForward(float)
  • IA_MoveRight(float)
  • IA_Jump(bool)
  • IA_Turn(float)
  • IA_LookUp(float)

IA_MoveForward动作资产配置举例:

在这里插入图片描述

再创建1个InputMappingContext,将前面新建的诸多动作资产添加入内(记得对轴对应的按键中的一个作取反Negate操作,否则两个按键将对应同一行为,如MoveForward中对S键取反),并添加相应的按键绑定:

在这里插入图片描述

所有资产在ContentBrowser视图下的显示:

在这里插入图片描述

代码层面,进入Character类(自定义的继承自Character类),改写其中部分代码:

UCLASS(config=Game)
class AInsideEnhancedInputCharacter : public ACharacter
{
	...
	
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category="EnhancedInput")
	UInputMappingContext* InputMappingContext;
	
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category="EnhancedInput|Action")
	UInputAction* IA_MoveForward;
	
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category="EnhancedInput|Action")
	UInputAction* IA_MoveRight;
	
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category="EnhancedInput|Action")
	UInputAction* IA_Turn;
	
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category="EnhancedInput|Action")
	UInputAction* IA_LookUp;
	
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category="EnhancedInput|Action")
	UInputAction* IA_Jump;

protected:

	/** Called for forwards/backward input */
	void MoveForward(const FInputActionValue& Value);

	/** Called for side to side input */
	void MoveRight(const FInputActionValue& Value);

	/** 
	 * Called via input to turn at a given rate. 
	 * @param Rate	This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
	 */
	void TurnAtRate(const FInputActionValue& Value);

	/**
	 * Called via input to turn look up/down at a given rate. 
	 * @param Rate	This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
	 */
	void LookUpAtRate(const FInputActionValue& Value);
	
	...
...

void AInsideEnhancedInputCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	// 保留原Input系统的输入响应
	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_MoveForward)
		{
			EnhancedInputComponent->BindAction(IA_MoveForward, ETriggerEvent::Triggered, this, &AInsideEnhancedInputCharacter::MoveForward);
		}

		if(IA_MoveRight)
		{
			EnhancedInputComponent->BindAction(IA_MoveRight, ETriggerEvent::Triggered, this, &AInsideEnhancedInputCharacter::MoveRight);
		}

		if(IA_Turn)
		{
			EnhancedInputComponent->BindAction(IA_Turn, ETriggerEvent::Triggered, this, &AInsideEnhancedInputCharacter::TurnAtRate);
		}

		if(IA_LookUp)
		{
			EnhancedInputComponent->BindAction(IA_LookUp, ETriggerEvent::Triggered, this, &AInsideEnhancedInputCharacter::LookUpAtRate);
		}

		if(IA_Jump)
		{
			EnhancedInputComponent->BindAction(IA_Jump, ETriggerEvent::Started, this, &AInsideEnhancedInputCharacter::Jump);
			EnhancedInputComponent->BindAction(IA_Jump, ETriggerEvent::Completed, this, &AInsideEnhancedInputCharacter::StopJumping);
		}
	}
}

...

void AInsideEnhancedInputCharacter::TurnAtRate(const FInputActionValue& Value)
{
	// calculate delta for this frame from the rate information
	AddControllerYawInput(Value.GetMagnitude() * TurnRateGamepad * GetWorld()->GetDeltaSeconds());
}

void AInsideEnhancedInputCharacter::LookUpAtRate(const FInputActionValue& Value)
{
	// calculate delta for this frame from the rate information
	AddControllerPitchInput(Value.GetMagnitude() * TurnRateGamepad * GetWorld()->GetDeltaSeconds());
}

void AInsideEnhancedInputCharacter::MoveForward(const FInputActionValue& Value)
{
	if ((Controller != nullptr) && (Value.IsNonZero()))
	{
		// find out which way is forward
		const FRotator Rotation = Controller->GetControlRotation();
		const FRotator YawRotation(0, Rotation.Yaw, 0);

		// get forward vector
		const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
		AddMovementInput(Direction, Value.GetMagnitude());
	}
}

void AInsideEnhancedInputCharacter::MoveRight(const FInputActionValue& Value)
{
	if ( (Controller != nullptr) && (Value.IsNonZero()) )
	{
		// find out which way is right
		const FRotator Rotation = Controller->GetControlRotation();
		const FRotator YawRotation(0, Rotation.Yaw, 0);
	
		// get right vector 
		const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
		// add movement in that direction
		AddMovementInput(Direction, Value.GetMagnitude());
	}
}

这样,编译过后,在相应的Character蓝图界面,可以进行绑定:

在这里插入图片描述

最终效果视频:

到这里,我们基本就用EnhancedInput完成了对第三人称模板的改造。

当然还没完,如果只是能够完成之前就已有的工作,那并不能说明这套新玩意的必要性。后面我们来逐渐引入一些不同的特性。

总结

简单总结,在EnhancedInput输入系统的扩展下,我们多了一些可以操作配置的资产,是我们能够实现输入时做一些特别的事情,比如IMC可以让我们配置动作和按键的映射,可以让我们指定哪些输入是生效的;比如IA可以让我们定义一个个的动作;比如Modifier和Trigger可以配置按键生效的条件和生效的效果等等。

普通游戏开发并不需要了解核心代码的部分,掌握其使用已经颇为难得,阅读代码可以进一步加深输入配置、输入响应的流程的理解,但是究其目的本源的话,还是希望以此精进自己对引擎的理解,提升自己的综合能力。

参考

虚幻 5.0 Documentation - Input

虚幻 5.0 Documentation - Lyra Input Settings

知乎作者 Yimi81 的文章《UE5 – EnhancedInput(增强输入系统)》

虚幻中文直播第39期

<think>我们正在使用Unreal Engine 5,并且要添加增强输入模块。根据引用[1]和[2],我们知道Unreal Engine具有模块化架构和插件系统,同时支持C++和蓝图编程。增强输入模块(Enhanced Input)是UE5中用于处理输入的现代化系统,它替代了旧的输入系统,提供了更强大的功能,如输入动作映射、上下文、修饰器和触发器等。 在UE5中,增强输入模块默认是启用的,但我们需要确保正确配置和使用它。以下是添加和使用增强输入模块的步骤: 1. **启用增强输入模块**: 在项目的`.Build.cs`文件中添加增强输入模块的依赖。打开项目源代码文件夹中的`[YourProjectName].Build.cs`文件(位于`Source/[YourProjectName]`目录下),在`PublicDependencyModuleNames`数组中添加`"EnhancedInput"`模块。例如: ```csharp PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput" // 添加EnhancedInput模块 }); ``` 2. **配置输入系统**: 在项目设置中,将默认的输入类设置为增强输入系统。打开编辑器,进入“编辑(Edit)” -> “项目设置(Project Settings)” -> “引擎(Engine)” -> “输入(Input)”。在“默认输入类(Default Input Classes)”部分,将“Default Player Input”设置为“EnhancedPlayerInput”,并将“Default Input Component”设置为“EnhancedInputComponent”。 3. **创建输入动作和输入上下文**: - **输入动作(Input Action)**:在内容浏览器中右键单击,选择“输入(Input)” -> “输入动作(Input Action)”。创建一个输入动作(例如`IA_Jump`),并设置其触发条件(如按下、释放、长按等)。 - **输入上下文(Input Mapping Context)**:同样在内容浏览器中右键单击,选择“输入(Input)” -> “输入映射上下文(Input Mapping Context)”。创建一个输入映射上下文(例如`IMC_Default`),然后将输入动作映射到具体的按键或轴输入,并可以添加修饰器(如组合键)和触发器(如双击检测)。 4. **在角色或控制器中设置输入**: 在玩家控制器(Player Controller)或角色(Character)的类中,我们需要在代码中获取增强输入组件,并将输入映射上下文绑定到该组件上。通常,在`SetupInputComponent`函数中进行设置(注意:由于我们使用了增强输入,不再使用`BindAction`等旧方法,而是通过输入映射上下文)。 示例代码(在角色类中): ```cpp // 头文件中声明 #include "InputAction.h" #include "InputMappingContext.h" UPROPERTY(EditAnywhere, Category="Input") UInputMappingContext* DefaultMappingContext; UPROPERTY(EditAnywhere, Category="Input") UInputAction* JumpAction; void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); // 转换为EnhancedInputComponent if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent)) { // 绑定JumpAction到Jump函数 EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, this, &AMyCharacter::Jump); } } void AMyCharacter::BeginPlay() { Super::BeginPlay(); // 获取玩家控制器 if (APlayerController* PlayerController = Cast<APlayerController>(Controller)) { // 获取本地玩家子系统 if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer())) { // 添加默认的输入映射上下文 Subsystem->AddMappingContext(DefaultMappingContext, 0); } } } ``` 5. **处理输入事件**: 在绑定输入动作时,我们可以指定不同的事件类型(如Triggered, Started, Completed等),然后在对应的函数中实现逻辑。例如,跳跃动作在Triggered时执行跳跃,在Completed时停止跳跃(如果需要)。 6. **调试**: 在运行游戏时,可以使用控制台命令`ShowDebug EnhancedInput`来查看增强输入系统的调试信息。 注意事项: - 确保在项目设置中正确设置了输入类,否则将无法使用增强输入系统。 - 输入映射上下文可以叠加,并设置优先级,优先级高的会覆盖优先级低的相同输入动作。 - 增强输入系统支持多种输入设备(如键盘、鼠标、手柄、触摸等),并且可以处理复杂的输入情况。 通过以上步骤,我们就在Unreal Engine 5项目中添加并使用了增强输入模块。这为我们的项目提供了更灵活、更强大的输入处理能力[^1][^2]。 §§相关问题§§ 1. 如何在UE5中处理多个输入映射上下文? 2. 增强输入系统如何处理不同设备(如手柄和键盘)的输入差异? 3. 在UE5增强输入系统中如何实现输入动作的修饰器(Modifiers)和触发器(Triggers)?</think>在 Unreal Engine 5 中添加增强输入模块(Enhanced Input System)需要遵循以下步骤,结合引擎的模块化架构和蓝图/C++集成特性: ### 步骤 1:启用增强输入模块 1. 在项目配置文件中启用模块(修改 `YourProjectName.Build.cs`): ```csharp PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput" // 添加增强输入模块 }); ``` 2. 重启引擎使配置生效 ### 步骤 2:配置项目设置 1. 编辑器菜单:**编辑 → 项目设置 → 引擎 → 输入** 2. 将 **默认输入类** 改为 `EnhancedPlayerInput` 3. 将 **默认输入组件** 改为 `EnhancedInputComponent`[^1] ### 步骤 3:创建输入资产(蓝图) 1. **输入动作(Input Action)**: - 内容浏览器右键 → **输入输入动作** - 定义动作类型(布尔/轴值/触发器) ```mermaid graph LR A[InputAction] --> B[Press] A --> C[Release] A --> D[Axis] ``` 2. **输入映射上下文(Input Mapping Context)**: - 内容浏览器右键 → **输入输入映射上下文** - 将按键/手柄输入映射到动作: ```mermaid graph TB Keyboard_W -->|绑定| IA_MoveForward Gamepad_LeftY -->|绑定| IA_MoveForward ``` ### 步骤 4:在角色蓝图中实现输入 ```cpp // 头文件声明 UPROPERTY(EditDefaultsOnly, Category="Input") UInputMappingContext* DefaultMappingContext; UPROPERTY(EditDefaultsOnly, Category="Input") UInputAction* MoveAction; // 在SetupPlayerInputComponent中绑定 void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { if (UEnhancedInputComponent* EnhancedInput = CastChecked<UEnhancedInputComponent>(PlayerInputComponent)) { EnhancedInput->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AMyCharacter::Move); } } ``` ### 步骤 5:高级功能配置 1. **输入修饰器(Modifiers)**: - 添加输入曲线处理(如摇杆死区调整) - 实现输入归一化:$ x_{norm} = \frac{x - x_{min}}{x_{max} - x_{min}} $ 2. **触发器(Triggers)**: - 配置双击检测:$ t_{double} < 0.3s $ - 设置长按触发阈值 ### 注意事项 1. **多平台适配**: - 通过 `UEnhancedInputLocalPlayerSubsystem` 动态切换映射上下文 ```cpp GetLocalPlayer()->GetSubsystem<UEnhancedInputLocalPlayerSubsystem>() ->AddMappingContext(KeyboardContext, 0); ``` 2. **输入优先级**: - 映射上下文可设置优先级值(高优先级覆盖低优先级) 3. **调试工具**: - 控制台命令 `showdebug enhancedinput` 显示实时输入数据 4. **与旧系统兼容**: - 可在 `DefaultInput.ini` 中配置新旧系统共存过渡方案[^2] > **性能提示**:避免在输入事件中执行重型操作,复杂逻辑应通过延迟处理或事件分发实现。移动端需特别注意输入采样率优化:$ f_s \geq 2f_{max} $(根据奈奎斯特定理)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Claude的羽毛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值