Loading the catalog…
Loading the catalog…
[Cogito 개발기 #03] 전투 로직을 GAS로 옮기는 과정 Cogito의 CombatComponent 에는 이전 전투 구현이 주석으로 남아 있다. 그 안에는 공격 종류 판단, 콤보 입력, 몽타주 재생, 차지 공격, 회전 공격, 피해 효과 적용 코드가 들어 있다. 현재 실행되는 코드에서는 이 중 상당 부분이 Gameplay Ability로 이동했다. 이번 글에서는 남아 있는 이전 코드와 현재 코드를 비교해, 전투 기능의 책임이 어떻게 달라졌는지 정리한다. 1. 이전 전투 코드가 처리하던 일 기존 콤보 관련 코드는 CombatComponent 안에서 다음과 같은 흐름을 가졌다. Attack1 / Attack2 ↓ 현재 공격 종류와 실행 조건 검사 ↓ ProcessComboCommand ↓ ComboActionBegin ↓ Montage 재생 ↓ SetComboCheckTimer ↓ ComboCheck ↓ 다음 Section 이동 또는 공격 종료 이 구조에서는 컴포넌트가 충돌 검사뿐 아니라 공격의 시작, 진행, 종료도 관리했다. 차지 공격과 회전 공격까지 들어오면 컴포넌트 안에서 관리할 상태가 늘어난다. 현재 공격 종류, 차지 여부, 몽타주 종료 시 복구할 이동 상태 등을 함께 추적해야 하기 때문이다. 현재 구조에서는 이런 행동 단위의 처리가 Ability로 이동해 있다. 2. 전환 이후 역할 비교 처리 내용 이전 코드 현재 코드 콤보 단계와 선입력 CombatComponent CogitoGA_AttackBase 공격 몽타주 재생과 종료 CombatComponent 공격 Ability와 Ability Task 차지 공격 컴포넌트 내부 함수 CogitoGA_ChargeAttack 회전 공격 컴포넌트 내부 함수 CogitoGA_Tornado 공격 충돌 검사 CombatComponent CombatComponent 기본 공격 경로의 피해 효과 적용 컴포넌트의 이전 코드 CogitoGA_AttackBase::OnHitEventReceived 핵심은 충돌 판정을 유지하면서 행동의 생명주기를 Ability로 옮겼다는 점이다. CombatComponent 는 공격이 누구에게 닿았는지 검사하고, Ability는 해당 공격을 어떻게 진행하고 종료할지 관리한다. 3. 이 구조에서 사용하는 GAS 요소 Cogito의 전투 흐름을 이해하는 데 필요한 요소를 간단히 정리하면 다음과 같다. 요소 이 글에서의 역할 AbilitySystemComponent 캐릭터에게 부여된 Ability와 효과를 관리하는 중심 객체 Gameplay Ability 공격·방어·회피처럼 실행과 종료가 있는 행동 AttributeSet 체력, 공격력, 방어력, 스태미나 같은 수치 Gameplay Effect 비용, 피해, 회복 지연 등의 효과 Ability Task 몽타주 재생이나 이벤트 수신처럼 진행 중인 Ability의 작업 GAS에서는 Ability를 부여하는 일과 실행하는 일이 구분된다. 실행 시에는 조건을 검사하고, CommitAbility 를 통해 설정된 비용과 쿨다운을 처리할 수 있다. 공식 문서 4. 캐릭터에 Ability 부여하기 플레이어의 PossessedBy 에서는 DefaultAbilities 에 설정된 클래스를 순회하며 Ability를 부여한다. if (HasAuthority()) { for (TSubclassOf<UGameplayAbility> AbilityClass : DefaultAbilities) { if (AbilityClass) { AbilitySystemComponent->GiveAbility( FGameplayAbilitySpec( AbilityClass, 1, INDEX_NONE, this ) ); } } } 이후 ASC의 Actor Info를 초기화한다. AbilitySystemComponent->InitAbilityActorInfo( this, this ); 현재 플레이어 코드에서는 Owner와 Avatar에 모두 플레이어 캐릭터 자신을 전달한다. GiveAbility 는 실행할 수 있는 Ability를 등록하는 단계다. 실제 공격은 이후 입력 처리에서 별도로 요청한다. 5. 입력은 실행 요청으로 바뀐다 일반 약공격을 처음 실행하는 경로에서는 태그로 Ability 활성화를 요청한다. FGameplayTag AttackTag = FGameplayTag::RequestGameplayTag( TEXT("Ability.Attack.Light") ); AbilitySystemComponent->TryActivateAbilitiesByTag( FGameplayTagContainer(AttackTag) ); 이미 공격 중이면 같은 공격을 새로 시작하지 않고 콤보 입력 이벤트를 전달한다. FGameplayEventData Payload; AbilitySystemComponent->HandleGameplayEvent( FGameplayTag::RequestGameplayTag( TEXT("Event.Attack.ComboInput") ), &Payload ); 이렇게 입력 처리와 콤보 진행을 나눈다. 캐릭터는 새 공격을 요청할지, 진행 중인 공격에 입력을 전달할지 판단한다. 다음 콤보로 넘어가는 시점과 단계 관리는 Ability가 담당한다. 6. Ability 안에서 실행 흐름 관리하기 CogitoGA_AttackBase 는 활성화되면 먼저 비용과 쿨다운 커밋을 시도한다. if (!CommitAbility( Handle, ActorInfo, ActivationInfo)) { EndAbility( Handle, ActorInfo, ActivationInfo, true, true ); return; } 그다음 회복 지연 효과를 적용하고, 공격 몽타주를 확인한 뒤 실행 상태를 초기화한다. CurrentCombo = 1; bHasNextComboCommand = false; 몽타주 재생에는 UAbilityTask_PlayMontageAndWait 를 사용한다. UAbilityTask_PlayMontageAndWait* PlayMontageTask = UAbilityTask_PlayMontageAndWait:: CreatePlayMontageAndWaitProxy( this, NAME_None, AttackMontage ); 현재 코드는 완료와 블렌드 아웃을 정상 종료 함수로 연결하고, 중단과 취소를 취소 종료 함수로 연결한다. 공격 실행 중에는 두 가지 이벤트도 기다린다. Event.Attack.Hit : 타격 결과 전달 Event.Attack.ComboInput : 다음 콤보 입력 전달 콤보 입력 대기는 ComboActionData 가 있을 때만 설정한다. 따라서 콤보 데이터가 없어도 몽타주가 있으면 단발 공격 경로로 실행할 수 있다. 7. 적중 결과를 Ability에 전달하기 전투 컴포넌트는 충돌 결과를 다음과 같이 전달한다. FGameplayEventData Payload; Payload.Instigator = Character; Payload.Target = HitActor; Payload.EventMagnitude = DamageMultiplier; UAbilitySystemBlueprintLibrary::SendGameplayEventToActor( Character, GetAttackHitEventTag(), Payload ); 여기서 이벤트를 보내는 대상은 공격자 캐릭터다. 맞은 적은 Payload.Target 에 들어 있다. 공격자의 Ability가 이 이벤트를 받아 대상의 ASC를 찾고 피해 효과를 적용한다. 이 구조에서는 역할이 다음처럼 나뉜다. CombatComponent └─ 적중 대상과 공격 배율 전달 Attack Ability └─ 공격자·대상의 능력치 조회 피해량 계산 Gameplay Effect 적용 8. 종료 처리도 Ability 안으로 옮긴다 공격이 끝나면 콤보 타이머와 내부 상태를 정리한다. if (UWorld* World = GetWorld()) { World->GetTimerManager().ClearTimer( ComboTimerHandle ); } CurrentCombo = 0; bHasNextComboCommand = false; Super::EndAbility( Handle, ActorInfo, ActivationInfo, bReplicateEndAbility, bWasCancelled ); 공격 시작 함수만 옮기고 종료 처리를 남겨 두면 책임 분리가 불완전해진다. 현재 코드는 콤보 상태와 타이머를 Ability에서 생성하고 같은 Ability의 종료 시점에 정리한다. 이 연결이 전환 과정에서 중요한 부분이다. 다음 글에서는 이 연결에 사용되는 Gameplay Tag를 다룬다. 행동을 식별하는 태그, 현재 상태를 나타내는 태그, 이벤트를 구분하는 태그를 나누어 살펴본다. 관련 코드 CombatComponent.cpp CogitoGA_AttackBase.cpp MyCharacterPlayer.cpp
What RADAR observed and classified to build this opportunity. It is what the source published, not a verification that the offer is still active.
[Cogito 개발기 #03] 전투 로직을 GAS로 옮기는 과정. [Cogito 개발기 #03] 전투 로직을 GAS로 옮기는 과정 Cogito의 CombatComponent 에는 이전 전투 구현이 주석으로 남아 있다. 그 안에는 공격 종류 판단, 콤보 입력, 몽타주 재생, 차지 공격, 회전 공격, 피해 효과 적용 코드가 들어 있다. 현재 실행되는 코드에서는 이 중 상당 부분이 Gameplay Ability로 이동했다. 이번 글에서는 남아 있는 이전 코드와 현재 코드를 비교해, 전투 기능의 책임이 어떻게 달라졌는지 정리한다. 1. 이전 전투 코드가 처리하던 일 기존 콤보 관련 코드는 CombatComponent 안에서 다음과 같은 흐름을 가졌다. Attack1 / Attack2 ↓ 현재 공격 종류와 실행…
Open source