10.01 - TIL

김혁·2025년 10월 1일

TIL

목록 보기
30/84

오늘의 코드카타

오늘의 공부

팀 프로젝트 진행 내용

1. WBP에서 애니메이션 재생이 정상적으로 되지 않는 에러 해결

  • 상황
    • 타이틀 화면에서 WBP를 통해 애니메이션을 재생시키고자 했는데, 애니메이션이 정상적으로 출력이 되지 않음
    • WBP에서 Event Construct를 통해서 Play Animation을 실행을 하는데, 로그를 찍어보니 로그도 출력이 안 됨
    • WBP에서 Event On Initialized를 통해서 로그를 출력해보니, 로그 출력은 되나 애니메이션 재생은 안 됨 -> 하지만 Delay를 통해 지연시키고 애니메이션 재생을 하니 정상적으로 재생됨
  • 원인 및 해결
    • UI 맡으신 분이 블루프린트로만 만들었다고 해서 블루프린트로만 확인을 했는데, 다른 분이 C++로 UserWidget을 만들어서 상속받아서 사용하는 구조였음
    • NativeConstruct() 함수에서 Super::NativeConstruct() 호출을 해주지 않아서 정상적으로 Construct 과정이 생략되어서 Event Construct가 정상적으로 작동하지 않았음

2. 모이 먹기 진행 중에 점프 시에 모이 먹기가 캔슬되게 수정

  • 캐릭터가 점프 실행 시에 ASC를 통해 모이 먹기 Ability 태그를 검사해서 있으면 캔슬하는 방향으로 가고자 함
  • Ability가 발동 중일 때, ASC에 태그를 부착하기 위해 ActivationOwnedTags를 활용해서 임시로 부착함. 점프 실행 시에 CancelAbilities() 함수를 활용해서 Tag가 부착된 Ability를 캔슬하고자 했는데, 정상적으로 동작이 되지 않음
    -> ChatGPT한테 물어보았는데, Ability에 추가적으로 AbilityTags에 태그를 할당해야 함

Tag 구분하기

  • AbilityTags
    • Ability 자체가 어떤 성격을 가지고 있는가를 나타내는 태그
    • Ability는 어떤 분류인지 나타내는 정적인 메타 정보
    • AbilitySpec에 항상 들어있음
  • ActivationOwnedTags
    • Ability가 실제로 발동 중일 때 ASC에 임시로 부착되는 태그
    • Ability가 활성화되면 ASC에 추가되고, Ability가 끝나면 자동으로 제거됨
  • CancelAbilities()
    • ASC는 현재 실행 중인 다른 Ability들의 AbilityTags를 확인하고 캔슬함
    • ActivationOwnedTags는 실행 중이라고 알려주는 태그이고, 구분을 하지 못하기 때문에 Ability 자체를 구분하기 위해서는 AbilityTags에 할당이 필요함

3. AI가 화내는 중에 다른 플레이어에게 공격받을 시에 화내는 시간이 연장되도록 수정

  • 기존에는 AI가 공격받았을 시에 Blackboard 값 변경을 하게 되면 BT에서 화내는 Ability를 실행하는 구조로 되어있는데, Blackboard 값이 이미 화내는 상태인 경우에 다시 Ability를 실행시킬 수 없음
    -> 따라서 공격받았을 시에 바로 Ability를 실행시키고, BT에서 화내는 Ability를 실행시키는 부분을 없애는 구조로 변경을 함
  • TryActivateAbilityByClass()를 통해서 Ability를 실행시키면 이미 Ability가 실행되고 있으면 갱신되는 것이 아니라 기존의 것이 유지되고 시도는 캔슬이 됨
    -> 따라서 Ability 실행 전에 CancelAllAbilities()를 통해서 실행되고 있는 Ability를 캔슬하고 실행되게끔 구현
    -> AI는 BT를 통해 하나씩 Ability가 실행이 되기 때문에 다른 Ability가 캔슬되는 걱정은 하지 않아도 될 것으로 보임

오늘의 CS

언리얼의 메모리 관리

  • UObject 기반 객체 : 언리얼의 GC 시스템이 자동 관리
  • UObject 기반이 아닌 C++ 객체나, 구조체 : 언리얼의 스마트 포인터를 통해 관리
  • 내부적으로 Low-Level에서는 전체적인 메모리 관리 전략은 메모리 풀을 활용

Garbage Collection

  • 모든 UObject는 언리얼의 Garbage Collection이 관리
  • 객체가 더 이상 참조되지 않으면 GC 사이클에서 해제됨 : 엔진 틱 중 특정 시점에 모아서 수행
  • GC에 등록하는 방법
    • 객체 생성 : NewObject() 또는 SpawnActor()를 통해 생성하면서 등록
    • 객체 참조 : UPROPERTY() 매크로를 통해 멤버 변수가 GC에 등록이 됨

GC 동작 원리

  • Mark & Sweep 방식으로 동작
    • Mark 단계 : 루트 집합으로 시작해서, 참조되는 객체들을 전부 살아있음으로 표시
    • Sweep 단계 : 참조되지 않는 객체는 더 이상 쓰이지 않음으로 표시 -> 메모리 해제
  • Mark와 Sweep의 작업은 게임 스레드에 히치(랙)을 유발시킬 수 있음.
  • 이를 해결하기 위해 증분 GC와 병렬 처리를 사용
  • 증분 GC
    • GC 작업을 여러 프레임에 걸쳐 작은 단위로 나누어 수행
    • 배경 GC
      • 대부분의 작업은 게임플레이 프레임 사이에 백그라운드 스레드에서 진행
      • 이 작업을 여러 프레임에 걸쳐 나누어 수행하므로, 한 프레임에서 발생하는 지연 시간을 최소화함
    • 스레드 세이프티
      • GC 작업이 백그라운드에서 실행되는 동안, 객체의 상태가 변경되거나 새로운 객체가 생성될 수 있음
      • GC 작업 중에도 객체 상태의 일관성을 유지하기 위해 내부적인 메커니즘을 가지고 있음
    • Sweep 단계는 메인 게임 스레드에서 이루어질 수 있기 때문에, 어느 정도의 히치가 발생 가능
  • 병렬 처리
    • 특히 시간이 오래 걸리는 Mark 및 최종 정리(Clean up) 과정은 여러 코어에서 병렬적으로 수행
    • 병렬 마크
      • 루트 객체에서 시작하여 참조를 따라 객체를 표시하는 마크 단계를 여러 스레드가 동시에 메모리 영역을 스캔하도록 분할
    • 클러스터링
      - 관련 있는 객체들을 클러스터로 묶어서 관리
      - GC가 실행될 때, 클러스터 단위로 작업을 처리하면 객체 간의 참조 관계를 빠르게 파악하고 병렬 처리하기가 용이해짐


메모리 풀

  • 일반적인 C++ 객체 및 내부 자료 구조를 위해 메모리 풀을 활용
  • 작동 방식
    • 미리 정해진 크기의 메모리 블록을 할당
    • 필요할 때마다 그 풀에서 메모리를 꺼내쓰고 반납하는 방식으로 작동
  • 장점
    • 할당/해제 속도 향상 : 기본 메모리 할당 함수를 호출하는 것은 느림
      -> 메모리 풀을 사용하면 풀 내부에서 포인터만 조정하는 매우 빠른 할당/해제 작업 가능
    • 메모리 파편화 감소 : 유사한 크기의 객체들을 연속적인 메모리 공간에 배치하여 메모리 파편화를 줄여줌
  • 언리얼 엔진에서는 내부적으로 Intel의 TBB(Threading Building Blocks)를 활용하여 사용 중임
profile
게임 개발자를 향해..

0개의 댓글