當前位置:網站首頁>虛幻5新特性之EnhancedInput

虛幻5新特性之EnhancedInput

2022-05-14 11:02:16Athrun_阿斯蘭

提要

本文是對虛幻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期

版權聲明
本文為[Athrun_阿斯蘭]所創,轉載請帶上原文鏈接,感謝
https://cht.chowdera.com/2022/134/202205141100542127.html

隨機推薦