-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #124 from futurelabunseen/116-3강-캐릭터의-입력-처리
116 3강 캐릭터의 입력 처리
- Loading branch information
Showing
35 changed files
with
379 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
# 3강: 캐릭터의 입력 처리 | ||
|
||
- 강의 목표 | ||
- 플레이어 캐릭터의 게임플레이 어빌리티 시스템 설정 방법의 학습 | ||
- 플레이어 캐릭터의 입력에 따른 게임플레이 어빌리티 발동의 구현 | ||
- 어빌리티 태스크의 활용 방법의 학습 | ||
- 게임플레이 어빌리티 시스템의 디버깅 방법의 학습 | ||
|
||
*어빌리티 태스크* | ||
|
||
## 플레이어 캐릭터의 ASC 설정 | ||
|
||
- 일반적으로 플레이어에 ASC를 설정할 때, Owner를 PlayerState로 설정하고, Avatar를 Character로 설정한다. | ||
|
||
### 게임플레이 어빌리티 스펙 | ||
|
||
- 게임플레이 어빌리티에 대한 정보를 담고 있는 구조체 | ||
- ASC는 직접 어빌리티를 참조하지 않고 스펙 정보만 가지고 있다. | ||
- 스펙은 어빌리티의 현재 상태와 같은 다양한 정보를 가지고 있다. | ||
- ASC로부터 어빌리티를 다루고자 할 경우 스펙에 있는 Handle을 사용해 컨트롤함 | ||
- 핸들 값은 전역으로 설정되어 있으며 스펙 생성시 자동으로 1씩 증가함. 기본값 -1 | ||
- 어빌리티 정보: 스펙 | ||
- 어빌리티 인스턴스에 대한 레퍼런스: 스펙 핸들 | ||
|
||
### 어빌리티 시스템 컴포넌트의 입력 처리 | ||
|
||
- 게임 어빌리티 스펙에는 입력 값을 설정하는 필드 InputID가 제공된다. | ||
- ASC에 등록된 스펙을 검사해 입력에 매핑된 GA를 찾을 수 있음: FindAbilitySpecFromInputID | ||
- 사용자 입력이 들어오면 ASC에서 입력에 관련된 GA를 검색함 | ||
- 해당 GA를 발견하면, 현재 발동 중인지를 판별 | ||
- GA가 발동 중이면 입력이 왔다는 신호를 전달: AbilitySpecInputPressed | ||
- GA가 발동하지 않았으면 새롭게 발동시킴: TryActivateAblity | ||
- 입력이 떨어지면 동일하게 처리 | ||
- GA에게 입력이 떨어졌다는 신호를 전달: AbilitySpecInputReleased | ||
|
||
### 게임플레이 어빌리티의 인스턴싱 옵션 | ||
|
||
- 상황에 따라 다양한 인스턴스 정책을 지정할 수 있다. | ||
- NonInstanced: 인스턴싱 없이 CDO에서 일괄 처리 | ||
- InstancedPerActor: 액터마다 하나의 어빌리티 인스턴스를 만들어 처리 | ||
- InstancePerExecution: 발동시 인스턴스를 생산함 | ||
|
||
### 어빌리티 태스크의 활용 | ||
|
||
- 어빌리티 태스크를 줄여 AT라고 함 | ||
- 게임플레이 어빌리티의 실행은 한 프레임에서 일어나고 | ||
- 게임플레이 어빌리티가 시작되면 EndAbility함수가 호출되기 전에는 끝나지 않음 | ||
- 애니메이션 재생 같이 시간이 소요되고 상태를 관리해야 하는 어빌리티의 구현 방법 | ||
- 비동기적으로 작업이 수행하고 끝나면 결과를 통보받는 형태로 구현 | ||
- 이를 위해 GAS는 어빌리티 태스크를 제공함 | ||
- 어빌리티 태스크의 활용 패턴 | ||
- 어빌리티 태스크에 작업이 끝나면 보르드캐스팅되는 종료 델리게이트를 선언 | ||
- GA는 TA를 생성한 후 바로 종료 델리게이트를 구독함 | ||
- GA의 구독 설정이 완료되면 AT를 구동: AT의 ReadyForActivation 함수 호출 | ||
- AT의 작업이 끝나면 델리게이트를 구독한 GA의 콜백 함수가 호출됨 | ||
- GA의 콜백함수가 호출되면 GA의 EndAbility 함수를 호출해 GA종료 | ||
- GA는 필요에 따라 다수의 AT를 사용해 복잡한 액션 로직을 설계할 수 있다 | ||
|
||
### GA의 블루프린트 상속 및 게임플레이 태그 설정 | ||
|
||
- 꼭 필요한 상황이 아니라면 GA와 TA는 가급적 자기 역할만 충실하게 구현하는 것이 좋다. | ||
- 게임플레이 태그를 C++에서 설정하는 경우 기획 변경때마다 소스코드 컴파일을 수행해야 함 | ||
- 게임플레이 태그 설정은 블루프린트에서 설정하는 것이 의존성 분리에 도움이 된다. | ||
- 게임플레이 태그 설정 기획 | ||
- 점프 GA의 ActivationOwendTags에 Character.IsJumpimng 게임플레이 태그 설정과 같이 사용 | ||
|
||
## 정리 | ||
|
||
- 플레이어 캐릭터의 GAS 설정 방법 | ||
- 오너액터와 아바타액터의 개념의 이해 | ||
- 플레이어 스테이트에서 ASC를 설정하는 이유 | ||
- 게임플레이 어빌리티 스펙의 이해 | ||
- GAS에 관련된 입력을 범용적으로 처리하는 방식의 학습 | ||
- GA의 다양한 인스턴싱 옵션의 확인 | ||
- GA에서 다양한 인스턴싱 옵선의 확인 | ||
- GAS의 디버깅 방법 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Binary file modified
BIN
+40 Bytes
(100%)
UghProject/Content/ThirdPerson/Blueprints/BP_ThirdPersonCharacter.uasset
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added
BIN
+35.1 KB
UghProject/Content/Ugh/Blueprints/Character/BP_UGCharacterPlayer.uasset
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added
BIN
+19.1 KB
UghProject/Content/Ugh/Blueprints/Game/BP_UGCharacterController.uasset
Binary file not shown.
Binary file modified
BIN
-19 Bytes
(100%)
UghProject/Content/Ugh/Blueprints/Game/BP_UGGameMode.uasset
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
97 changes: 97 additions & 0 deletions
97
UghProject/Source/UghProject/Character/UGCharacterPlayer.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
// Fill out your copyright notice in the Description page of Project Settings. | ||
|
||
|
||
#include "Character/UGCharacterPlayer.h" | ||
|
||
#include "AbilitySystemComponent.h" | ||
#include "EnhancedInputComponent.h" | ||
#include "Player/UGPlayerState.h" | ||
|
||
AUGCharacterPlayer::AUGCharacterPlayer() | ||
{ | ||
ASC = nullptr; | ||
} | ||
|
||
UAbilitySystemComponent* AUGCharacterPlayer::GetAbilitySystemComponent() const | ||
{ | ||
return ASC; | ||
} | ||
|
||
void AUGCharacterPlayer::PossessedBy(AController* NewController) | ||
{ | ||
Super::PossessedBy(NewController); | ||
|
||
AUGPlayerState* GASPS = GetPlayerState<AUGPlayerState>(); | ||
if (GASPS) | ||
{ | ||
ASC = GASPS->GetAbilitySystemComponent(); | ||
ASC->InitAbilityActorInfo(GASPS, this); | ||
|
||
for (const auto& StartAbility : StartAbilities) | ||
{ | ||
FGameplayAbilitySpec StartSpec(StartAbility); | ||
ASC->GiveAbility(StartSpec); | ||
} | ||
|
||
for (const auto& StartInputAbility : StartInputAbilities) | ||
{ | ||
FGameplayAbilitySpec StartSpec(StartInputAbility.Value); | ||
StartSpec.InputID = StartInputAbility.Key; | ||
ASC->GiveAbility(StartSpec); | ||
} | ||
|
||
SetupGASInputComponent(); | ||
|
||
APlayerController* PlayerController = CastChecked<APlayerController>(NewController); | ||
PlayerController->ConsoleCommand(TEXT("showdebug abilitysystem")); | ||
} | ||
} | ||
|
||
void AUGCharacterPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) | ||
{ | ||
Super::SetupPlayerInputComponent(PlayerInputComponent); | ||
|
||
SetupGASInputComponent(); | ||
} | ||
|
||
void AUGCharacterPlayer::SetupGASInputComponent() | ||
{ | ||
if (IsValid(ASC) && IsValid(InputComponent)) | ||
{ | ||
UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(InputComponent); | ||
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, this, &AUGCharacterPlayer::GASInputPressed , 0); | ||
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &AUGCharacterPlayer::GASInputReleased , 0); | ||
EnhancedInputComponent->BindAction(AttackAction, ETriggerEvent::Triggered, this, &AUGCharacterPlayer::GASInputPressed, 1); | ||
} | ||
} | ||
|
||
void AUGCharacterPlayer::GASInputPressed(int32 InputId) | ||
{ | ||
FGameplayAbilitySpec* Spec = ASC->FindAbilitySpecFromInputID(InputId); | ||
|
||
if (Spec) | ||
{ | ||
Spec->InputPressed = true; | ||
if (Spec->IsActive()) | ||
{ | ||
ASC->AbilitySpecInputPressed(*Spec); | ||
} | ||
else | ||
{ | ||
ASC->TryActivateAbility(Spec->Handle); | ||
} | ||
} | ||
} | ||
|
||
void AUGCharacterPlayer::GASInputReleased(int32 InputId) | ||
{ | ||
FGameplayAbilitySpec* Spec = ASC->FindAbilitySpecFromInputID(InputId); | ||
if (Spec) | ||
{ | ||
Spec->InputPressed = false; | ||
if (Spec->IsActive()) | ||
{ | ||
ASC->AbilitySpecInputReleased(*Spec); | ||
} | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
UghProject/Source/UghProject/Character/UGCharacterPlayer.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Fill out your copyright notice in the Description page of Project Settings. | ||
|
||
#pragma once | ||
|
||
#include "CoreMinimal.h" | ||
#include "AbilitySystemInterface.h" | ||
#include "Character/UGCharacterBase.h" | ||
#include "UGCharacterPlayer.generated.h" | ||
|
||
/** | ||
* | ||
*/ | ||
UCLASS() | ||
class UGHPROJECT_API AUGCharacterPlayer : public AUGCharacterBase, public IAbilitySystemInterface | ||
{ | ||
GENERATED_BODY() | ||
|
||
public: | ||
AUGCharacterPlayer(); | ||
|
||
virtual class UAbilitySystemComponent* GetAbilitySystemComponent() const override; | ||
virtual void PossessedBy(AController* NewController) override; // 빙의가 될 때 호출 | ||
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; | ||
|
||
FORCEINLINE class UAnimMontage* GetAttackMontage() const { return AttackMontage; } | ||
|
||
protected: | ||
void SetupGASInputComponent(); | ||
void GASInputPressed(int32 InputId); | ||
void GASInputReleased(int32 InputId); | ||
|
||
protected: | ||
UPROPERTY(EditAnywhere, Category = GAS) | ||
TObjectPtr<class UAbilitySystemComponent> ASC; | ||
|
||
UPROPERTY(EditAnywhere, Category = GAS) | ||
TArray<TSubclassOf<class UGameplayAbility>> StartAbilities; | ||
|
||
UPROPERTY(EditAnywhere, Category = GAS) | ||
TMap<int32, TSubclassOf<class UGameplayAbility>> StartInputAbilities; | ||
|
||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Stat, Meta = (AllowPrivateAccess = "true")) | ||
TObjectPtr<class UAnimMontage> AttackMontage; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// Fill out your copyright notice in the Description page of Project Settings. | ||
|
||
|
||
#include "GAS/UGGA_Attack.h" | ||
|
||
#include "GasExample.h" | ||
#include "Character/UGCharacterBase.h" | ||
#include "GameFramework/CharacterMovementComponent.h" | ||
#include "Abilities/Tasks/AbilityTask_PlayMontageAndWait.h" | ||
#include "Character/UGCharacterPlayer.h" | ||
|
||
UUGGA_Attack::UUGGA_Attack() | ||
{ | ||
InstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor; | ||
} | ||
|
||
void UUGGA_Attack::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) | ||
{ | ||
Super::ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData); | ||
|
||
AUGCharacterPlayer* ABCharacter = CastChecked<AUGCharacterPlayer>(ActorInfo->AvatarActor.Get()); | ||
ABCharacter->GetCharacterMovement()->SetMovementMode(MOVE_None); | ||
|
||
UAbilityTask_PlayMontageAndWait* PlayAttackTask = UAbilityTask_PlayMontageAndWait::CreatePlayMontageAndWaitProxy(this, TEXT("PlayAttack"), ABCharacter->GetAttackMontage()); | ||
PlayAttackTask->OnCompleted.AddDynamic(this, &UUGGA_Attack::OnCompleteCallback); | ||
PlayAttackTask->OnInterrupted.AddDynamic(this, &UUGGA_Attack::OnInterruptedCallback); | ||
PlayAttackTask->ReadyForActivation(); | ||
} | ||
|
||
void UUGGA_Attack::InputPressed(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo) | ||
{ | ||
GAS_LOG(LogABGAS, Log, TEXT("Begin")); | ||
} | ||
|
||
void UUGGA_Attack::CancelAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateCancelAbility) | ||
{ | ||
Super::CancelAbility(Handle, ActorInfo, ActivationInfo, bReplicateCancelAbility); | ||
|
||
} | ||
|
||
void UUGGA_Attack::EndAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateEndAbility, bool bWasCancelled) | ||
{ | ||
Super::EndAbility(Handle, ActorInfo, ActivationInfo, bReplicateEndAbility, bWasCancelled); | ||
|
||
AUGCharacterBase* ABCharacter = CastChecked<AUGCharacterBase>(ActorInfo->AvatarActor.Get()); | ||
ABCharacter->GetCharacterMovement()->SetMovementMode(MOVE_Walking); | ||
} | ||
|
||
void UUGGA_Attack::OnCompleteCallback() | ||
{ | ||
bool bReplicatedEndAbility = true; | ||
bool bWasCancelled = false; | ||
EndAbility(CurrentSpecHandle, CurrentActorInfo, CurrentActivationInfo, bReplicatedEndAbility, bWasCancelled); | ||
} | ||
|
||
void UUGGA_Attack::OnInterruptedCallback() | ||
{ | ||
bool bReplicatedEndAbility = true; | ||
bool bWasCancelled = true; | ||
EndAbility(CurrentSpecHandle, CurrentActorInfo, CurrentActivationInfo, bReplicatedEndAbility, bWasCancelled); | ||
} |
Oops, something went wrong.