Unreal Project/문제

FloatingDamage 구조 문제

갠소롱 2025. 4. 30. 22:46

🧩 왜 FloatingDamage를 GameInstanceSubsystem에서 처리했는가

처음에는 Floating Damage를 일반적인 UI처럼 처리하려고 했다. FloatingDamageManager라는 매니저 클래스를 만들고, 이를 HUD에서 관리하도록 했다.


🚧 구조적 한계

적 캐릭터가 데미지를 받을 때, FloatingDamageManager를 통해 화면에 데미지를 띄워야 한다. 그런데 FloatingDamageManager는 플레이어의 HUD에 종속되어 있어서, 적 캐릭터의 BeginPlay()에서는 직접 접근이 불가능하다.

결국 EnemyCharacter에서 아래와 같은 경로로 접근해야 한다.

EnemyCharacter
  └── GetWorld()->GetFirstPlayerController()
        └── GetHUD()
              └── GetFloatingDamageManager()

이 방식은 접근 경로가 지나치게 복잡하고, 적 캐릭터가 플레이어 컨트롤러나 HUD에 의존해야 한다는 점에서 구조적으로 부적절하다.


📡 멀티플레이 환경 고려

현재는 싱글 플레이 환경이라 직접적인 문제는 없지만, 멀티플레이 게임으로 확장할 경우 PlayerController와 HUD가 여러 개 존재하게 된다.

그 상황에서 모든 적 캐릭터가 각 플레이어의 HUD를 탐색하며 FloatingDamageManager를 호출하는 구조는 말이 되지 않는다. 객체 간 참조 관계도 복잡해지고, 게임 전반의 유지보수에도 부정적인 영향을 준다.


✅ GameInstanceSubsystem으로 대체

Floating Damage는 단순한 UMG 위젯이 아닌, WidgetComponent를 가진 액터로 따로 만들었다. 그리고 이 액터는 URMFloatingDamageSubsystem이라는 GameInstanceSubsystem에서 관리하도록 변경했다.

이렇게 설계한 이유는 다음과 같다:

  • Subsystem은 전역 시스템이기 때문에, 적 캐릭터든 플레이어든 어디서든 접근이 가능하다.
  • Floating Damage는 특정 플레이어나 HUD에 귀속된 기능이 아니며, 게임 전역에서 통합적으로 관리되어야 할 시각적 연출이다.
  • 멀티플레이에서도 구조적인 일관성을 유지할 수 있다.
URMFloatingDamageSubsystem* FloatingSubsystem = GetGameInstance()->GetSubsystem<URMFloatingDamageSubsystem>();

🏗️ 구조 비교

기존 방식 최종 방식
PlayerController → HUD → FloatingDamageManager → Widget
(우회적 접근 필요)
Enemy → GameInstanceSubsystem 직접 접근
→ Floating Damage Actor 생성 및 표시

📌 정리

처음에는 데미지를 띄우는 기능이니까 HUD에 넣는 것이 자연스럽다고 판단했다. 하지만 실제로 구현하려다 보니 참조 흐름이 복잡해졌고, 멀티플레이 환경까지 고려하면 이 구조는 한계가 분명했다.

결국 Floating Damage를 독립된 액터로 분리하고, 전역에서 관리할 수 있도록 GameInstanceSubsystem을 활용했다.