BlueRoseNote/03-UnrealEngine/Gameplay/GAS/GAS Ability输入绑定.md

123 lines
4.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Untitled
date: 2024-01-29 13:23:24
excerpt:
tags:
rating: ⭐
---
# 前言
相关函数主要为:
- AbilitySystemComponent->BindToInputComponent()只绑定名称为AbilityConfirm与AbilityCancel的InputAction。
- AbilitySystemComponent->BindAbilityActivationToInputComponent()输入InputComponent、FGameplayAbilityInputBinds、FTopLevelAssetPath枚举类路径、枚举ID之后绑定GA与Input。
- AbilitySystemComponent->SetBlockAbilityBindingsArray()设置Block列表。
# GAS
BindAbilityActivationToInputComponent()的绑定方式如果ASC在Character中可以在SetupPlayerInputComponent()中进行绑定:
```c
// Bind to AbilitySystemComponent
FTopLevelAssetPath AbilityEnumAssetPath = FTopLevelAssetPath(FName("/Script/GASDocumentation"), FName("EGDAbilityInputID"));
AbilitySystemComponent->BindAbilityActivationToInputComponent(PlayerInputComponent, FGameplayAbilityInputBinds(FString("ConfirmTarget"),
FString("CancelTarget"), AbilityEnumAssetPath, static_cast<int32>(EGDAbilityInputID::Confirm), static_cast<int32>(EGDAbilityInputID::Cancel)));
```
其内部主要是类似这样的方式进行绑定:
```c++
// 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);
}
```
AbilityLocalInputPressed()与AbilityLocalInputReleased()会执行:
1. 触发多播委托
2. TryActivateAbility() 或者 AbilitySpecInputPressed()。
感觉可以自己实现一个BindAbilityActivationToInputComponent()的绑定逻辑ASC自带的逻辑有点2。
GAS使用的是**InputComponent->AddActionBinding**,而增强输入使用**PlayerEnhancedInputComponent->BindAction**。本质是一样的。
```c++
FInputActionBinding& BindAction( const FName ActionName, const EInputEvent KeyEvent, UserClass* Object, typename FInputActionHandlerSignature::TMethodPtr< UserClass > Func )
{
FInputActionBinding AB( ActionName, KeyEvent );
AB.ActionDelegate.BindDelegate(Object, Func);
return AddActionBinding(MoveTemp(AB));
}
```
## 绑定输入而不激活能力
如果您不希望`GameplayAbilities`在按下输入时自动激活,但仍将它们绑定到输入以与 一起使用`AbilityTasks`,则可以向您的`UGameplayAbility`子类添加一个新的 bool 变量`bActivateOnInput`,该变量默认为`true`并覆盖`UAbilitySystemComponent::AbilityLocalInputPressed()`。
```c
void UGSAbilitySystemComponent::AbilityLocalInputPressed(int32 InputID)
{
// Consume the input if this InputID is overloaded with GenericConfirm/Cancel and the GenericConfim/Cancel callback is bound
if (IsGenericConfirmInputBound(InputID))
{
LocalInputConfirm();
return;
}
if (IsGenericCancelInputBound(InputID))
{
LocalInputCancel();
return;
}
// ---------------------------------------------------------
ABILITYLIST_SCOPE_LOCK();
for (FGameplayAbilitySpec& Spec : ActivatableAbilities.Items)
{
if (Spec.InputID == InputID)
{
if (Spec.Ability)
{
Spec.InputPressed = true;
if (Spec.IsActive())
{
if (Spec.Ability->bReplicateInputDirectly && IsOwnerActorAuthoritative() == false)
{
ServerSetInputPressed(Spec.Handle);
}
AbilitySpecInputPressed(Spec);
// Invoke the InputPressed event. This is not replicated here. If someone is listening, they may replicate the InputPressed event to the server.
InvokeReplicatedEvent(EAbilityGenericReplicatedEvent::InputPressed, Spec.Handle, Spec.ActivationInfo.GetActivationPredictionKey());
}
else
{
UGSGameplayAbility* GA = Cast<UGSGameplayAbility>(Spec.Ability);
if (GA && GA->bActivateOnInput)
{
// Ability is not active, so try to activate it
TryActivateAbility(Spec.Handle);
}
}
}
}
}
}
```
# SDHGame
李兄是在状态机每个节点的StateBegin()中调用CreateDynamicSkillInputActionMappingContext()进行动态绑定的。FSDHSkillInputActionBinding里包含FEnhancedActionKeyMapping相关数据。
```c++
void USDHSMStateIns::OutputActionKeyMapping(TArray<FEnhancedActionKeyMapping>& OutBindings, const TArray<FSDHSkillInputActionBinding>& InputSkillBinding)
{
for (int32 i = 0; i < InputSkillBinding.Num(); i++)
{
FEnhancedActionKeyMapping NewMapping;
NewMapping.Key = InputSkillBinding[i].Key;
NewMapping.Action = InputSkillBinding[i].Action;
OutBindings.Add(MoveTemp(NewMapping));
}
}
```