当前位置:   article > 正文

虚幻5新特性之EnhancedInput_ue5增强输入

ue5增强输入

提要

本文是对虚幻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"});
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

这样,不论在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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
使用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);
	
	...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
...

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());
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87

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

在这里插入图片描述

最终效果视频:

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

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

总结

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

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

参考

虚幻 5.0 Documentation - Input

虚幻 5.0 Documentation - Lyra Input Settings

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

虚幻中文直播第39期

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/714434
推荐阅读
相关标签
  

闽ICP备14008679号