2024-01-29 15:04:48 +08:00
|
|
|
|
---
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2024-02-02 11:35:59 +08:00
|
|
|
|
# 暂时需要使用GAS默认的枚举绑定Input的理由
|
|
|
|
|
GameplayAbilitySpec.h的InputPressed:
|
|
|
|
|
```c++
|
|
|
|
|
UPROPERTY(NotReplicated)
|
|
|
|
|
uint8 InputPressed:1;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
该变量用于本地输入判断,可以使用自己的代码代替,但涉及到以下几个函数,工作量比较大。
|
|
|
|
|
- UAbilitySystemComponent
|
|
|
|
|
- AbilityLocalInputReleased
|
|
|
|
|
- AbilitySpecInputPressed
|
|
|
|
|
- InternalServerTryActivateAbility
|
|
|
|
|
- InternalTryActivateAbility
|
|
|
|
|
- TryActivateAbility
|
|
|
|
|
- 间接关系
|
|
|
|
|
- BindAbilityActivationToInputComponent
|
|
|
|
|
- SetBlockAbilityBindingsArray
|
|
|
|
|
- PressInputID
|
|
|
|
|
- ReleaseInputID
|
|
|
|
|
- UAbilityTask_WaitInputPress
|
|
|
|
|
- UAbilityTask_WaitInputRelease
|
|
|
|
|
|
2024-02-02 12:39:48 +08:00
|
|
|
|
理论上是可以将其修改成增强输入的版本,只需要将枚举循环改成InputActionContext循环即可,具体逻辑在角色类中
|
|
|
|
|
```c++
|
|
|
|
|
void AGSHeroCharacter::BindASCInput()
|
|
|
|
|
{
|
|
|
|
|
if (!bASCInputBound && IsValid(AbilitySystemComponent) && IsValid(InputComponent))
|
|
|
|
|
{
|
|
|
|
|
AbilitySystemComponent->BindAbilityActivationToInputComponent(InputComponent, FGameplayAbilityInputBinds(FString("ConfirmTarget"),
|
|
|
|
|
FString("CancelTarget"), FString("EGSAbilityInputID"), static_cast<int32>(EGSAbilityInputID::Confirm), static_cast<int32>(EGSAbilityInputID::Cancel)));
|
|
|
|
|
|
|
|
|
|
bASCInputBound = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FGameplayAbilityInputBinds(FString InConfirmTargetCommand, FString InCancelTargetCommand, FTopLevelAssetPath InEnumPathName, int32 InConfirmTargetInputID = INDEX_NONE, int32 InCancelTargetInputID = INDEX_NONE)
|
|
|
|
|
: ConfirmTargetCommand(InConfirmTargetCommand)
|
|
|
|
|
, CancelTargetCommand(InCancelTargetCommand)
|
|
|
|
|
, EnumPathName(InEnumPathName)
|
|
|
|
|
, ConfirmTargetInputID(InConfirmTargetInputID)
|
|
|
|
|
, CancelTargetInputID(InCancelTargetInputID)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**ConfirmTarget**、**CancelTarget**需要在DefaultInput.ini中添加对应的配置(名字需要对应)。
|
|
|
|
|
**EGSAbilityInputID**为枚举类名称,**EGSAbilityInputID::Confirm**与**EGSAbilityInputID::Cancel**为枚举的index需要与GameplayAbilitySpec中的AbilityInputID对应。具体是在GiveAbility中进行,参考[[#GASShooter中给Ability注册按键ID]]。
|
|
|
|
|
|
|
|
|
|
之后还需要在URPGGameplayAbility中将枚举**ERPGAbilityInputID**修改成
|
|
|
|
|
```c++
|
|
|
|
|
UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "RPGGameplayAbility|Input")
|
|
|
|
|
ERPGAbilityInputID AbilityInputID = ERPGAbilityInputID::None;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## GASShooter中给Ability注册按键ID
|
|
|
|
|
```c++
|
|
|
|
|
void AGSCharacterBase::AddCharacterAbilities()
|
|
|
|
|
{
|
|
|
|
|
// Grant abilities, but only on the server
|
|
|
|
|
if (GetLocalRole() != ROLE_Authority || !IsValid(AbilitySystemComponent) || AbilitySystemComponent->bCharacterAbilitiesGiven)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (TSubclassOf<UGSGameplayAbility>& StartupAbility : CharacterAbilities)
|
|
|
|
|
{
|
|
|
|
|
AbilitySystemComponent->GiveAbility(
|
|
|
|
|
FGameplayAbilitySpec(StartupAbility, GetAbilityLevel(StartupAbility.GetDefaultObject()->AbilityID), static_cast<int32>(StartupAbility.GetDefaultObject()->AbilityInputID), this));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AbilitySystemComponent->bCharacterAbilitiesGiven = true;
|
|
|
|
|
}
|
|
|
|
|
```
|
2024-02-02 11:35:59 +08:00
|
|
|
|
|
2024-01-29 15:04:48 +08:00
|
|
|
|
# SDHGame
|
2024-01-29 15:46:03 +08:00
|
|
|
|
李兄是在状态机每个节点的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));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|