25년 4월

2주차

AI의 ComboData를 PawnGameData를 통해 로드하도록 구현 

플레이어는 무기마다 콤보를 갖고 있고, AI는 Pawn 단위로 갖고 있도록 구현

 

몬스터 공격 AI 구현

InRange 데코레이터로 거리 감지 후 어빌리티(공격) 실행

AIController에서 몬스터 관련 정보를 소유하도록 구현

공격을 진행하기 위해 서버에서 다음 콤보를 요청하기 때문에 즉시 콤보 데이터를 가져올 수 없어 다음 콤보를 예측하여 반환하도록 구현

MonsterDataTable에서 MonsterGameDataPath를 저장하여 콤보 데이터를 가져올 수 있도록 구현

 

인벤토리 UI 구현

EnhancedInputSystem을 활용하여 인벤토리 토글 구현

인벤토리에 아이템이 추가될 때 인벤토리 슬롯 추가되도록 구현

인벤토리 슬롯 StackCount 동기화

 

ActorGameData을 액터가 반환하도록 변경

기존에는 액터 타입에 따라 ActorExtensionComponent에서 ActorGameData를 구했기 때문에 코드가 복잡해져 구조 변경 필요

따라서 각 액터가 ActorGameData를 반환하도록 가상 함수로 구현

 

플레이어의 Input 로직을 PlayerController로 이동

PlayerController의 원래 역할에 Input 담당이 있고, 플레이어 폰이 계속 교체될 때 Input이 그대로 유지되도록 하기 위함

 

25년 3월

5주차

플레이어의 적 탐지를 클라이언트에서만 처리하도록 변경

적 탐지 로직은 플레이어의 락온 기능, 적 인식 관련 애니메이션에 영향을 미치는데, 클라이언트 변조를 통해 조작되더라도 게임 밸런스에 심각한 영향을 주지 않는다고 판단했습니다. 결과적으로 클라이언트 측 탐지로 인한 불공정한 이점은 미미하다고 판단하였습니다.
탐지와 락온 시스템의 반응성 개선 및 서버의 감지 연산 부담 감소, 패킷 전송 감소 효과를 얻음

4주차

장비를 장착할 때 WeaponAttributeSet을 추가하도록 구현

데이터테이블에서 WeaponAttributeSet 경로를 저장하고 로드

EquipmentComponent에서 장비를 장착할 때 WeaponAttributeSet을 AbilitySystemComponent에 추가하도록 요청

서버에서 장착에 성공했을 때 클라이언트에 RPC로 Notify를 보내서 동기화하도록 구현

 

공격 안되는 버그 수정
OnEquipWeapon이 실행될 때 클라이언트에 WeaponAttributeSet이 아직 리플리케이트 되지 않는 상태이므로 콤보 초기화가 되지 않았기 때문에 버그 발생

추후 콤보(스킬) 데이터는 런타임에 변경되지 않기 때문에 스킬 데이터테이블로 이동할 예정이기 때문에 일단 임시로 장비 데이터테이블에서 WeaponAttributeSet을 가져와 생성한 것을 바탕으로 콤보 초기화를 수행

 

3주차

리플리케이트를 사용하는 컴포넌트를 서버에서만 생성하도록 변경

리플리케이트를 사용하는 컴포넌트는 서버에서 등록한다면 서버를 통해 관리되는 컴포넌트를 클라이언트에 복제하므로 서버에서만 생성하여 불필요한 생성을 방지

 

리팩토링(적을 탐지하는 책임을 DetectComponent->PawnSensingComponent로 이동)

책임을 분할하여 컴포넌트의 변경 이유를 이동시켜 응집도를 향상시키고, 언리얼 엔진의 프레임워크를 사용하여 가독성 향상된다고 판단

DetectComponents는 PawnSensingComponent에서 탐지한 폰을 전달 받아 적들을 관리

적을 탐지하는 코드를 클라에서 서버로 이동

 

GameplayTag 리플리케이트할 때 Count가 -1에서 1이 되는 버그 수정

FMinimalReplicationTagCountMap::NetSerialize 과정에서 TagMap의 모든 태그를 1로 만들기 때문에 발생

-1이 아닌 0으로 설정하여 태그를 삭제하여 해결

 

AbilitySystemComponent를 이용한 컴포넌트 초기화를 델리게이트에서 인터페이스의 메서드를 호출하도록 변경

컴포넌트 초기화 시점에서 델리게이트에 바인딩하는 것이 AbilitySystemComponent를 초기화하는 시점과 충돌하는 부분이 있어 인터페이스를 통해 의존성을 높여 명확하게 초기화하도록 변경

 

탐지한 InteractableActor를 처리하는 로직을 InteractionComponent로 이동

객체지향 설계에 맞게 Interaction 책임이 있는 InteractionComponent에서 처리하여 변경의 이유를 줄이고, 코드를 파악하기 쉬워졌다고 판단

 

2주차

데이터테이블 로드 후에 에셋 로드를 위해 PostLoadDataTable 함수 구현

GameDataSubsystem에서 데이터테이블을 모두 로드한 후에 데이터테이블의 PostLoadDataTable를 실행

데이터테이블에서 로드된 후에 필요한 작업이 있다면 PostLoadDataTable를 오버라이드하여 구현하도록 설계

AIDataTable에서 BT, BB Path를 저장하기 때문에 각 에셋을 로드하기 위해 구현

게임 시작 전 필요한 데이터 및 에셋을 한번에 로딩하는 것이 적합하다고 판단했기 때문

 

비헤이비어 트리를 실행하기 위한 기본 설계 및 탐지한 적으로 이동 구현

AIController::OnPossess에서 데이터테이블에서 로드한 비헤이비어 트리 및 블랙보드 실행

AIController는 AI를 관리해야 하기 때문에 서버에서만 실행되기 때문에 DetectComponent에서 탐지한 적을 RPC로 서버에 동기화(추후에 서버에서 검증해야 함)

탐지한 적을 BlackBoard에 설정하고 BT에서 적으로 이동

 

25년 2월

2주차

인터렉션 UI에서 NativeOnKeyDown이 호출되지 않는 현상 수정

인터렉션 UI가 켜질 때 SetFocus 설정하여 UI에 키 입력이 되도록 수정

 

인터렉션 데이터를 데이터테이블에서 가져와서 데이터에 따라 인터렉션 UI가 동작하도록 구현

인터렉션 이름(ex 대화하기)를 표시하고, 인터렉션을 실행하기 위해 필요한 키 홀드 타임을 설정

NativeOnKeyDown에서 타이머를 설정하고 NativeOnKeyUp에서 타이머를 해제하여 Down~Up사이에 키 홀드 타임이 충족되면 인터렉션 실행하도록 구현

 

GameInstance를 가져올 때 GetWorldFromContextObject로 가져오도록 변경

기존에는 서브시스템의 static Get 함수에서 GameViewport으로부터 GameInstance를 가져왔는데 서버에서 GameViewport가 없기 때문에 크래시 발생

WorldContextObject(World)를 전달받아 World에서 GameInstance를 가져오도록 수정함

 

인터렉션 어빌리티 실행 구현

인터렉션 UI에서 인터렉션 컴포넌트에 요청하여 어빌리티 실행

인터렉션 UI -> 클라이언트 플레이어 인터렉션 컴포넌트 -> RPC를 통해 서버 플레이어 인터렉션 컴포넌트 -> 서버 타겟 액터 인터렉션 컴포넌트 -> 인터렉션 어빌리티 실행

어빌리티 실행을 통해 DisableInteraction 태그가 클라이언트에 리플리케이트되어 인터렉션 불가능으로 판단

 

데미지와 관련된 Attribute 구조 변경

공격/스킬의 추가 데미지를 적용하기 위해 AttackDamage Attribute 추가

공격 판정이 시작되기 전에 공격에 대한 GameplayEffect가 적용되어 AttackDamage 증가

위의 경우는 공격 추가 데미지를 무기 데미지만큼 증가

 

UGameplayEffectExecutionCalculation에서 최종 데미지를 계산하여 타겟의 Damage 증가

 

스킬 자원(SR) Attribute 구현 및 강 공격 차지에 스킬 자원 적용

공격/스킬 GameplayEffect에 정의된 SR 소모 수치가 있을 때만 공격이 진행되도록 구현

공격이 진행될 때 GameplayEffect가 적용되어 SR 수치 감소

 

공격 판정이 되지 않는 버그 수정

각 공격 어빌리티 태그로 판정 범위를 가져와야 하는데 공격이 진행될 때 잘못된 어빌리티를 부여하여 판정 범위를 못 가져와서 공격 판정이 진행되지 않음

각 공격 어빌리티 태그를 제대로 부여하여 공격 판정을 진행

 

SR(스킬 자원) 스텟 표시 UI 구현

플레이어의 SR을 Tick마다 스스로 Update

StatusWidget에서 StatusType만 설정하면 다양한 스텟을 표시할 수 있도록 재활용성, 확장성 있게 구현

 

DamageAttack이 중첩으로 증가하는 버그 수정

GameplayEffect에서 Add로 DamageAttack을 증가시키고 초기화하지 않았기 때문에 발생

Override로 값을 바꾸도록 수정

 

스킬 시스템 구현 및 테스트 스킬 추가

스킬 시스템은 공격 시스템이 필요하고, 추후 컷신 등 스킬의 기능을 추가해야 하므로 Attack 어빌리티를 상속받음

공격과 동일한 방법으로 추가할 수 있도록 구현

 

SkillComponent 리팩토링

Skill은 컨트롤러가 있는 Pawn만 가능하므로 PawnComponent를 상속받도록 변경
서버에서만 다음 콤보를 진행해야 하기 때문에 어썰트 추가

 

PlayerStatusUserWidget->StatusUserWidget으로 이름 변경

플레이어 뿐만 아니라 보스의 체력 등을 표시할 수 있기 때문에 포괄적인 이름으로 변경

 

클라이언트에 스텟이 리플리케이트되지 않는 현상 수정

Attribute의 스텟을 선언할 때 Replicated로 선언하지 않았기 때문에 리플리케이트되지 않았음

 

공격할 때 시전자에 적용되는 GameplayEffect를 공격을 실행하자마자 발생하도록 변경

기존에는 GameplayEffect를 공격 판정의 결과를 받고 적용했지만 공격을 실행할 때 적용하는 것이 구조적으로 맞다고 판단

 

3주차

서버로 콤보 동기화 및 공격 관련 GameplayEffect를 서버에서 적용

Input과 어빌리티의 실행을 원활하게 하기 위해 어빌리티를 클라이언트에서만 실행

클라이언트에서 다음 콤보로 진행하면 서버 RPC를 보내서 서버에서 콤보를 동기화하도록 변경

공격 판정에서 TargetActor를 찾으면 서버 RPC를 보내서 서버에서 위치 검증 후 GameplayEffect를 적용하고, 스텟은 클라이언트에 Replicate로 동기화

(초기 구현으로 검증을 러프하게 하고, 추후 무기/공격/스킬 기획이 나왔을 때 추가)

 

Skill UI 구현

플레이어 스킬을 사용할 수 있으면 Opacity 1, 사용할 수 없으면 Opacity 0.3으로 변경하도록 구현

UI를 소유하고 있는 플레이어의 SkillComponent를 통해 스킬을 사용할 수 있는지 판정

Input GameplayTag를 변경하여 SkillWidget을 재사용할 수 있도록 설계

 

4주차

두 번째의 공격이 적용되지 않는 버그 수정

공격이 종료되면 클라이언트에서 콤보를 초기화하는데 서버로 초기화된 콤보를 동기화해주지 않아서 발생

RPC 함수를 선언하여 콤보를 동기화하여 해결함

 

피격 판정으로 인한 Hp가 닳지 않는 버그 수정

피격 GameplayEffect를 적용할 때 플레이어를 SourceActor로 설정하여 데미지 최종 계산에서 플레이어 스텟을 못 가져와서 발생

플레이어를 SourceActor가 아닌 Instigator로 설정하여 해결함

 

스킬 정보를 게임플레이 이펙트에서 가져오던 것을 데이터테이블에서 가져오도록 변경

스킬마다 BP 게임플레이이펙트를 생성하면 파일이 많아지고 버전 관리가 힘듦

따라서 스킬에 데이터테이블 RowName(키)를 입력하고, 데이터테이블에서 스킬 관련 정보를 가져오도록 변경

 

콤보 2타, 4타에 SR을 회복하도록 구현

콤보 2타, 4타 스킬 데이터테이블을 추가

공격의 TargetActor 탐색을 완료했을 때 PostSkillProcess를 실행하여 공격을 적중했을 때 SR을 회복하도록 구현

 

다른 종류가 섞인 콤보를 진행할 때 콤보가 초기화되는 버그 수정

어빌리티가 캔슬되지 않고 종료됐을 때만 콤보가 초기화되도록 수정

 

강 공격을 연타하면 두 번째 콤보가 시작될 때 기본 강 공격을 해도 차징 공격이 실행되는 버그 수정

공격 어빌리티가 InstancedPerActor로 설정되어 강 공격에 대한 객체가 유지되어 차징 관련 플래그의 기존 값이 새로운 공격에 그대로 적용되기 때문에 발생

EndAbility에서 플래그를 초기화하도록 변경

 

5주차

적을 탐지할 때 FilterClass로 해당 클래스인 액터만 탐지

플레이어일 때 Monster, Monster일 때 Player 클래스만 탐지하도록 OverlapActor 함수에 FilterClass를 설정

 

몬스터는 적을 탐지하는 코드가 서버에서 실행되는 버그 수정

클라이언트 코드를 IsLocallyControlled로 구분했으나 서버에서 LocalRole이 Authority이고, RemoteRole이 None이므로 해당 함수를 만족하여 버그 발생(함수를 잘못 사용)

따라서 NetMode가 DedicatedServer가 아닐 때에만 호출되도록 변경

 

25년 1월

1주차

AbilitySystemComponent 소유 액터를 PawnComponent로 변경

기존에 플레이어는 PlayerState에서 AbilitySystemComponent를 소유했지만 싱글 게임이므로 다른 클라이언트에 복제될 필요가 없고, 죽을 때 액터가 파괴되는 것이 아니고,

캐릭터가 변경돼도 Ability와 Mesh 등을 변경하면 되기 때문에 PawnComponent로 변경하여 구조가 단순해지고 참조가 줄어드는 이점 챙김

 

PlayerController의 락온에서 적 탐지하는 코드를 몬스터도 사용할 수 있도록 DetectComponent로 생성 및 이동

적을 탐지하는 책임을 PlayerController->DetectComponent로 이동

PlayerController는 락온이 활성화됐을 때 Pawn의 DetectComponent에서 탐지된 액터를 가져와서 카메라 조작

추가로 DetectComponent에서 적을 탐지했을 때 StatusComponent에서 전투 상태 돌입 구현

 

락온 마커 UserWidget 표시하는 과정에서 오차가 발생하는 버그 수정

Alignment를 (0,0) -> (0.5, 0.5)로 수정하여 위젯의 중심을 기준으로 설정하여 해결

 

락온 마커 UserWidget 위치 계산 코드 리팩토링

뷰포트와 Panel의 비율을 계산하여 ViewportScale을 직접 계산하는 코드를 UWidgetLayoutLibrary::GetViewportScale을 적용하여 간단하게 구현

 

2주차

AnimNotify_AttackHitCheck 대신 AnimNotify_SendGameplayEvent로 Common하게 사용하도록 클래스 이름 변경

GameplayTag를 설정한 AnimNotify를 통해 UAbilitySystemBlueprintLibrary::SendGameplayEventToActor 호출하여 AbilitySystem에 GameplayEvent를 보내는 기능으로 클래스의 이름을 변경하여 재사용성을 높임

 

SkillComponent에 콤보 공격 트리 구현

무기의 콤보 조합 데이터를 바탕으로 현재 공격에서 가능한 다음 공격(콤보)를 빠르게 가져오기 위해 트리 자료구조로 콤보 트리 구현

트리 노드를 생성할 때마다 TArray<TUniquePtr<FComboNode>>에 저장하여 자동으로 메모리 관리

게임플레이 태그로 콤보를 구분하고, 애니메이션 몽타주 등 콤보 데이터를 WeaponAttributeSet에 저장하여 참조

 

공격 어빌리티에서 기본/차징/콤보 공격 구현

일정 시간 후에 InputRelease를 하면 차징 공격으로 전환

SkillComponent의 콤보 트리에서 다음 공격(콤보)를 가져와 실행

단일 공격도 1 Combo라고 가정하여 통일된 구조로 공격을 하도록 구현

AnimNotify를 받아 특정 구간 내에서만 다음 공격 입력이 가능

같은 어빌리티 콤보가 이어지면 어빌리티가 종료되지 않음

 

플레이어가 죽었을 때 움직이는 현상 수정

플레이어가 죽었을 때 입력 비활성화되도록 수정

 

콤보 노드를 TWeakPtr로 변경하여 댕글링 방지

노드 로우 포인터를 TWeakPtr로 약한 참조를 유지하여 댕글링 체크를 하도록 변경

 

3주차

서버-클라이언트 구조로 전환

싱글플레이 기획이지만 추후 멀티플레이 전환 대비 및 서버-클라이언트 구조 학습을 위해 전환

기존 로직을 서버 혹은 클라이언트에 맞게 분리

게임이 시작된 후 클라이언트가 로그인하면 BeginPlay가 바로 호출되어 게임플레이 로직 초기화를 못하는 현상이 발생하여 어빌리티 시스템이 초기화될 때 게임플레이 로직을 초기화하도록 변경

네트워크 속도가 낮을 때 InputComponent 초기화가 안되는 현상이 발생하여 네트워크 속도가 정상적일 때는 SetupPlayerInputComponent에서 초기화하고 네트워크 속도가 낮을 때는 OnRep_PlayerState에서 초기화하도록 수정

 

플레이어의 AbilitySystemComponent 소유 액터를 PlayerState로 변경

플레이어의 태그 시스템을 통해 변경되는 캐릭터의 어빌리티 및 상태가 동일하게 적용하기 위해 PlayerState로 소유

 

4주차

인터렉션 액터 탐지 및 UI 구현

플레이어 좌, 우, 앞 2m 탐지된 액터 중 인터렉션이 가능하고, 플레이어와 가장 가까운 액터 탐지

인터렉션 액터를 탐지했을 때 UI로 이벤트를 전송하여 UI 표시

인터렉션 액터를 탐지하지 못하거나 화면에서 사라질 경우 UI Hidden

다이어그램 : DetectComponent->InteractionComponent->InteractionUserWidget

 

달리고 난 뒤 걷기 속도로 돌아오지 않는 현상 수정

Run 어빌리티가 서버에서 실행되어 InputReleased를 받지 못해 어빌리티가 종료되지 않았기 때문

Run 어빌리티를 클라이언트에서 실행되도록 하고, MaxWalkSpeed를 RPC를 통해 서버에 동기화

 

달리다가 걸을 때 회전이 즉시되는 현상 수정

bUseControllerRotationYaw가 false에서 true로 될 때(옆으로 달리다 걸을 때) 즉시 회전하는 문제가 원인

따라서 bUseControllerRotationYaw와 bOrientRotationToMovement 프로퍼티를 사용하지 않고 Input과 컨트롤러(카메라)의 방향으로 회전할 때 보간하도록 변경

 

Hp UI가 Hp를 반영하지 않는 현상 수정

뒤늦게 UI가 델리게이트를 구독하여 Hp가 초기화되는 시점에 델리게이트를 받지 못했기 때문에 발생

UI에서 Actor를 설정해주고 Tick마다 Actor의 스텟을 업데이트하도록 수정

 

콤보 노드 초기화가 되지 않아 공격이 안되는 버그 수정

무기 AttributeSet을 적절하지 않은 객체 StatusComponent에서 처리하고 있는 문제가 원인

EquipmentComponent에서 무기를 장착했을 때 무기 AttributeSet을 추가하고, 콤보 노드를 초기화하도록 변경

 

에디터에서 설정하던 데이터를 PrimaryDataAsset으로 로드하도록 변경

경로를 통해 오브젝트 레퍼런스를 로드하는 것이 아닌 PrimaryDataAsset으로 관리하여 수정에 유연하게 대응

액터 타입에 따라 컴포넌트를 동적으로 생성하기 위해 에디터에서 수정하지 못하도록 변경

 

구르기할 때 테스트 용도의 이동 로직이 정상적으로 작동하지 않는 현상 수정

테스트 용도로 캐릭터의 Velocity를 설정했었는데 서버-클라이언트 구조로 전환하면서 서버와 클라이언트의 Velocity가 동기화되지 않아서 발생

루트 모션으로 구르기를 구현하기로 결정됐으므로 이동 관련 로직을 삭제

 

InteractableActor를 TraceChannel로 필터링하도록 변경

수정 전 : 플레이어의 인터렉션 가능 범위에 있는 모든 Actor를 찾은 후 런타임에서 InteractionComponent 관련 필터링

수정 후 : TraceChannel로 HitResult를 가져온 후 InteractionComponent 관련 필터링

TraceChannel로 InteractableActor를 찾는 것이 엔진 레벨에서의 최적화를 얻어낼 수 있고, 적은 수의 액터에서 InteractionComponent를 찾는 과정이 효율적이라고 판단

 

5주차

ActorType에 따라서 컴포넌트를 생성할 수 있도록 인터페이스 생성

Npc, Player, Gimmick 등 여러 액터 타입에 따라 일관된 컴포넌트 생성 로직을 수행할 수 있도록 구현

+ Recent posts

목차