Calmer的文章

  • 首页
  • 文章归档
  • 关于页面

  • 搜索
体验游戏 笔记 推荐 工具链 工具使用 小游戏 插件 UI 软件 教程

UE5中GAS接入增强输入(EnhancedInput)

发表于 2023-07-18 | 分类于 游戏开发 | 0 | 阅读次数 3278

前言

UE5 GAS能够直接支持引擎常规输入, 在GA中能触发Wait Input Press、Wait Input Release等Task, 从而制作一些蓄力能力。
问题:项目使用的增强输入插件来完成更多的输入控制,但GAS本身对增强输入插件没有做支持,官方文档也没有做明确的描述,如何将GAS接入增强输入?

接入常规输入(参考官网文档4.6.2)

常规输入设置

image.png

接入步骤

  1. 声明InputID枚举
UENUM(BlueprintType)
enum class EUpCoAbilityInputID : uint8
{
	// 0 None
	None			UMETA(DisplayName = "None"),
	Confirm			UMETA(DisplayName = "Confirm"),
	Cancel			UMETA(DisplayName = "Cancel"),
	NormalAttack    UMETA(DisplayName = "NormalAttack"),
};
  1. 在GameplayAbility的子类中声明两个变量,AbilityInputID与AbilityID,用于此GA对应的Input枚举,并在GA中设置对应的枚举
UCLASS()
class UPGRADECOLLECTOR_API UUpCoGameplayAbility : public UGameplayAbility
{
	GENERATED_BODY()
public:

	// Abilities with this set will automatically activate when the input is pressed
	UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "Ability")
	EUpCoAbilityInputID AbilityInputID = EUpCoAbilityInputID::None;

	// Value to associate an ability with an slot without tying it to an automatically activated input.
	// Passive abilities won't be tied to an input so we need a way to generically associate abilities with slots.
	UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "Ability")
	EUpCoAbilityInputID AbilityID = EUpCoAbilityInputID::None;
	
};

image.png

  1. 在GiveAbility的时候,将GA与InputID Bind
void AUpCoCharacterBase::AddCharacterAbilities()
{
	// Grant abilities, but only on the server	
	if (GetLocalRole() != ROLE_Authority || !AbilitySystemComponent.IsValid() || AbilitySystemComponent->
		bCharacterAbilitiesGiven)
	{
		return;
	}

	for (TSubclassOf<UUpCoGameplayAbility>& StartupAbility : CharacterAbilities)
	{
		AbilitySystemComponent->GiveAbility(FGameplayAbilitySpec(StartupAbility,1, static_cast<int32>(StartupAbility.GetDefaultObject()->AbilityInputID),this));
	}

	AbilitySystemComponent->bCharacterAbilitiesGiven = true;
}
  1. 在Character SetupPlayerInputComponent中调用AbilitySystemComponent的BindAbilityActivationToInputComponent方法完成Bind
void AUpCoCharacterBase::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);
	BindASCInput();
}

void AUpCoCharacterBase::BindASCInput()
{
AbilitySystemComponent->BindAbilityActivationToInputComponent(InputComponent, FGameplayAbilityInputBinds(
	FString("ConfirmTarget"), // 对应着 ProjectSettings里面的Action名称
	FString("CancelTarget"), // 对应着 ProjectSettings里面的Action名称
	FTopLevelAssetPath("/Script/UpgradeCollector", TEXT("EUpCoAbilityInputID")), // 对应着枚举名称
	static_cast<int32>(EUpCoAbilityInputID::Confirm), //  Confirm
	static_cast<int32>(EUpCoAbilityInputID::Cancel) //  Cancel
	));															  ));
}
  1. 测试

image.png

增强输入

增强输入设置

image.png

接入思路

分析常规输入的接入bind,关键是AbilitySystemComponent中的BindAbilityActivationToInputComponent方法
源码

void UAbilitySystemComponent::BindAbilityActivationToInputComponent(UInputComponent* InputComponent, FGameplayAbilityInputBinds BindInfo)
{
	UEnum* EnumBinds = BindInfo.GetBindEnum();

	SetBlockAbilityBindingsArray(BindInfo);

	for(int32 idx=0; idx < EnumBinds->NumEnums(); ++idx)
	{
		const FString FullStr = EnumBinds->GetNameStringByIndex(idx);
		
		// Pressed event
		{
			FInputActionBinding AB(FName(*FullStr), IE_Pressed);
			AB.ActionDelegate.GetDelegateForManualSet().BindUObject(this, &UAbilitySystemComponent::AbilityLocalInputPressed, idx);
			InputComponent->AddActionBinding(AB);
		}

		// Released event
		{
			FInputActionBinding AB(FName(*FullStr), IE_Released);
			AB.ActionDelegate.GetDelegateForManualSet().BindUObject(this, &UAbilitySystemComponent::AbilityLocalInputReleased, idx);
			InputComponent->AddActionBinding(AB);
		}
	}

	// Bind Confirm/Cancel. Note: these have to come last!
	if (BindInfo.ConfirmTargetCommand.IsEmpty() == false)
	{
		FInputActionBinding AB(FName(*BindInfo.ConfirmTargetCommand), IE_Pressed);
		AB.ActionDelegate.GetDelegateForManualSet().BindUObject(this, &UAbilitySystemComponent::LocalInputConfirm);
		InputComponent->AddActionBinding(AB);
	}
	
	if (BindInfo.CancelTargetCommand.IsEmpty() == false)
	{
		FInputActionBinding AB(FName(*BindInfo.CancelTargetCommand), IE_Pressed);
		AB.ActionDelegate.GetDelegateForManualSet().BindUObject(this, &UAbilitySystemComponent::LocalInputCancel);
		InputComponent->AddActionBinding(AB);
	}

	if (BindInfo.CancelTargetInputID >= 0)
	{
		GenericCancelInputID = BindInfo.CancelTargetInputID;
	}
	if (BindInfo.ConfirmTargetInputID >= 0)
	{
		GenericConfirmInputID = BindInfo.ConfirmTargetInputID;
	}
}

其实发现在常规输入的情况下,InputComponent Bind几个Action,分别对应

  • AbilityLocalInputPressed
  • AbilityLocalInputReleased
  • LocalInputConfirm
  • LocalInputCancel

然后通过能力中的枚举ID关联起来了。

于是我们提出新的针对增强输入的解决方案

  1. 使用EnhancedInputComponent的方法进行bind
// Pressed event
{
	EnhancedInputComponent->BindAction(InputAction, ETriggerEvent::Started,this, &UAbilitySystemComponent::AbilityLocalInputPressed, idx);
}

// Released event
{
	EnhancedInputComponent->BindAction(InputAction, ETriggerEvent::Completed,this, &UAbilitySystemComponent::AbilityLocalInputReleased, idx);
}
  1. InputID枚举值映射InputAction

具体接入步骤

  1. 继承AbilitySystemComponent,在子类中重写BindAbilityActivationToInputComponent方法

.h文件

UCLASS()
class UPGRADECOLLECTOR_API UUpCoAbilitySystemComponent : public UAbilitySystemComponent
{
	GENERATED_BODY()
public:
	bool bCharacterAbilitiesGiven = false;
	bool bStartupEffectsApplied = false;
	virtual void BindAbilityActivationToInputComponent(UInputComponent* InputComponent, FGameplayAbilityInputBinds BindInfo) override;
};

.cpp文件

void UUpCoAbilitySystemComponent::BindAbilityActivationToInputComponent(UInputComponent* InputComponent,
                                                                        FGameplayAbilityInputBinds BindInfo)
{
	Super::BindAbilityActivationToInputComponent(InputComponent, BindInfo);
	UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(InputComponent);
	AUpCoCharacterBase* UpCoCharacter = Cast<AUpCoCharacterBase>(GetAvatarActor());
	if(!UpCoCharacter)
	{
		return;
	}
	TMap<EUpCoAbilityInputID, UInputAction*> CurrentMap = UpCoCharacter->GetEnumMap();
	
	if(EnhancedInputComponent)
	{
		UEnum* EnumBinds = BindInfo.GetBindEnum();
		SetBlockAbilityBindingsArray(BindInfo);
		for(int32 idx=0; idx < EnumBinds->NumEnums(); ++idx)
		{
			// const FString FullStr = EnumBinds->GetNameStringByIndex(idx)
			UInputAction* InputAction = CurrentMap.FindRef(static_cast<EUpCoAbilityInputID>(idx));
			if(InputAction)
			{
				// Pressed event
				{
					EnhancedInputComponent->BindAction(InputAction, ETriggerEvent::Started,this, &UAbilitySystemComponent::AbilityLocalInputPressed, idx);
				}

				// Released event
				{
					EnhancedInputComponent->BindAction(InputAction, ETriggerEvent::Completed,this, &UAbilitySystemComponent::AbilityLocalInputReleased, idx);
				}
			}
		}
	}
}
  1. InputID枚举值映射InputAction,在CharacterBase.h中声明变量,用于映射,并在Character蓝图中设置映射
  • 声明变量和Get方法
    image.png
    image.png
  • 设置映射
    image.png
  1. 后续同常规输入接入步骤一致
    在Character SetupPlayerInputComponent中调用AbilitySystemComponent的BindAbilityActivationToInputComponent方法完成Bind

总结

GAS是UE5官方提供的一套高度灵活的能力框架,已经被验证于多个在线商业项目使用,但其中还是有不少的细节需要在基础框架上进行完善和封装,也要求开发者对框架源代码有更多的理解,本文针对GAS集成增强输入提供了一种思路。

参考链接

https://github.com/tranek/GASDocumentation#462-binding-input-to-the-asc

  • 本文作者: Calmer
  • 本文链接: https://mytechplayer.com/archives/ue5中gas接入增强输入enhancedinput
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
UE5中GAS GE属性计算(GE优化)
UE5集成ChatGPT和Stable Diffusion(SD)
  • 文章目录
  • 站点概览
Calmer

Calmer

88 日志
7 分类
10 标签
RSS
Creative Commons
0%
© 2020 — 2025 Calmer
由 Halo 强力驱动
蜀ICP备20010026号-1川公网安备51019002006543
Copyright © 2020-2025 Calmer的文章