안동민 개발노트

본문 시작

게임 루프와 주요 클래스 구조

게임 루프 안에서 GameInstance·GameMode·Controller·Pawn·컴포넌트가 맡는 역할과 호출 흐름을 정리합니다.

이전 절에서는 C++ 클래스를 생성하고 블루프린트로 확장하는 흐름을 확인했습니다.

이번 절에서는 액터와 클래스가 매 프레임 어떤 순서로 업데이트되는지 이해하기 위해 언리얼 엔진의 게임 루프(Game Loop)와 이를 구성하는 주요 클래스들의 구조를 다룹니다.


게임 루프: 프레임 처리 흐름

모든 게임은 기본적으로 무한 반복되는 주기를 가지고 동작합니다.

이를 게임 루프라고 부릅니다.

언리얼 엔진도 매 프레임(Frame) 여러 작업을 수행하며 게임 세계를 업데이트합니다. 작업의 실행 주기와 스레드, 선후 관계는 각 시스템의 설정에 따라 달라집니다.

이 루프는 플레이어의 입력 처리, AI 업데이트, 물리 시뮬레이션, 애니메이션, 렌더링 등 게임 내의 모든 변화를 제어합니다.

프레임 처리에 참여하는 주요 작업은 다음과 같습니다. 이 목록은 전체 엔진의 고정된 실행 순서를 뜻하지 않습니다.

  • 입력 처리: 키보드·마우스·게임패드 입력을 게임 동작으로 연결합니다.
  • 게임 로직: 활성화된 액터의 Tick과 컴포넌트의 TickComponent가 지정된 주기로 실행됩니다. DeltaTime은 해당 틱에 전달된 경과 시간입니다.
  • 물리와 AI: 충돌·중력 등의 시뮬레이션과 환경 인식·행동 선택을 갱신합니다.
  • 렌더링과 사운드: 카메라·메시·텍스처·조명으로 화면을 만들고 음악과 효과음을 처리합니다.
  • 네트워크: 멀티플레이에서 필요한 상태를 정해진 복제 조건과 주기에 따라 교환합니다.

이 모든 과정이 매우 짧은 시간 안에 반복적으로 이루어지며, 이를 통해 우리가 보는 부드러운 게임 화면이 만들어집니다.

여러분이 AActor::Tick(float DeltaTime) 함수에 코드를 작성하면, 그 코드는 이 게임 로직 업데이트 단계에서 매 프레임마다 실행될 수 있습니다.

단, 필요한 액터나 컴포넌트에만 Tick을 켜는 편이 성능 관리에 유리합니다.

Tick의 실행 간격, Tick Group, 선행 틱 의존성을 설정할 수 있습니다. 매 프레임 처리가 필요한지부터 판단합니다.

업데이트가 필요한 시점에 맞춘 호출 방식

연속 갱신, 사건 반응, 주기 작업을 구분합니다.

업데이트가 필요한 시점에 맞춘 호출 방식
방식알맞은 작업주의할 경계
Tick연속 이동·보간처럼 주기적으로 갱신할 계산활성화·실행 간격·Tick Group·선행 의존성 확인
이벤트입력·충돌·상태 변경에 대한 반응사건이 발생하고 연결된 대상이 있을 때 호출
타이머일정 간격의 갱신이나 지연 작업프레임 처리의 영향을 받으므로 정확한 실시간 마감 보장 아님
Tick
알맞은 작업: 연속 이동·보간처럼 주기적으로 갱신할 계산
주의할 경계: 활성화·실행 간격·Tick Group·선행 의존성 확인
이벤트
알맞은 작업: 입력·충돌·상태 변경에 대한 반응
주의할 경계: 사건이 발생하고 연결된 대상이 있을 때 호출
타이머
알맞은 작업: 일정 간격의 갱신이나 지연 작업
주의할 경계: 프레임 처리의 영향을 받으므로 정확한 실시간 마감 보장 아님

컴포넌트는 로직을 담는 단위입니다. Tick·이벤트·타이머와 경쟁하는 별도의 호출 방식은 아닙니다.


주요 클래스 구조와 역할

언리얼 엔진의 게임 루프와 밀접하게 연관되어 게임의 전반적인 흐름을 제어하는 몇 가지 핵심 클래스들이 있습니다.

이 클래스들은 특정 역할을 전담하며, 서로 유기적으로 협력하여 하나의 게임을 완성합니다.

UGameInstance

  • 역할: UGameInstance는 게임 전체의 수명 주기 동안 유지되는 상위 레벨 객체입니다. 일반적인 실행 컨텍스트에서는 게임이 시작될 때 생성되어 게임이 종료될 때까지 유지됩니다.
  • 특징: 레벨이 변경되어도 파괴되지 않기 때문에, 같은 게임 인스턴스에서 레벨 전환을 넘어 유지할 데이터(예: 진행 상황, 설정, 세션 정보)를 관리할 수 있습니다. PIE 인스턴스마다 별도로 존재하며, 자동 네트워크 복제나 디스크 저장을 제공하는 것은 아닙니다.
  • 활용: 게임 전반에 걸친 데이터 관리, 세션 관리, 로딩 화면 전환, 설정 저장/로드 등에 사용됩니다.

AGameModeBase / AGameMode

  • 역할: AGameModeBase (또는 더 구체적인 게임 유형에 맞는 AGameMode)는 게임의 규칙과 흐름을 정의하는 클래스입니다. 예를 들어, 어떤 캐릭터 클래스를 사용할지, 플레이어의 스폰 지점은 어디인지, 점수 계산 방식은 무엇인지, 게임의 승리/패배 조건은 무엇인지 등을 설정합니다.
  • 특징: AGameMode는 서버에서만 존재하며, 클라이언트에는 복제되지 않습니다. 이는 게임 규칙이 서버에서 단일하게 관리되어야 함을 의미합니다. 클라이언트에서는 AGameStateBase (후술)가 게임 상태 정보를 공유받습니다.
  • 활용: 게임 모드 변경, 플레이어 접속/종료 처리, 게임 시작/종료 로직, 기본 Pawn/Controller/HUD 클래스 지정 등에 사용됩니다. 실제 UI 표시와 입력 처리는 보통 클라이언트의 PlayerController, HUD, Widget 쪽에서 담당합니다.

AGameStateBase / AGameState

  • 역할: AGameStateBase (또는 AGameState)는 게임의 현재 상태 정보를 모든 클라이언트와 공유하는 역할을 합니다. 즉, 게임의 규칙(AGameMode)에 따라 변동되는 플레이어 점수, 남은 시간, 현재 라운드, 참여 플레이어 목록 등과 같은 정보를 담고, 이를 모든 플레이어에게 전달합니다.
  • 특징: GameState는 서버에서 클라이언트로 상태를 전달하는 복제 경로를 제공합니다. 직접 추가한 변수도 자동 전송되는 것은 아니므로 복제 선언·등록 등 필요한 설정을 해야 합니다.
  • 활용: 점수판 업데이트, 라운드 정보 표시, 게임 진행 상태 표시 등에 사용됩니다.

APlayerController

  • 역할: APlayerController는 플레이어의 입력을 처리하고, 해당 플레이어가 조종하는 APawn 또는 ACharacter를 제어하는 클래스입니다. 키보드, 마우스, 게임패드 등의 입력 이벤트를 받고, 이를 게임 로직으로 변환하여 캐릭터를 움직이거나 상호작용하게 만듭니다.
  • 특징: 각 플레이어마다 하나씩 존재하며, 서버와 해당 플레이어의 클라이언트에 존재합니다. 다른 플레이어의 클라이언트에는 보통 해당 PlayerController가 직접 존재하지 않습니다. AI가 제어하는 캐릭터는 AAIController가 담당합니다.
  • 활용: 캐릭터 이동, 카메라 제어, UI 상호작용, 인벤토리 관리, 무기 발사 등 플레이어와 관련된 거의 모든 입력 및 상호작용 로직에 관여합니다.

APawn / ACharacter

  • 역할: APawn은 APlayerController나 AAIController에 의해 빙의(Possess)되어 제어될 수 있는 액터의 기본 클래스입니다. 즉, 플레이어나 AI가 월드 내에서 조종할 수 있는 실제 객체를 나타냅니다. ACharacter는 APawn을 상속받으며, 사람 형태의 이동과 관련된 복잡한 로직(걷기, 뛰기, 점프, 웅크리기 등)을 구현하는 데 특화되어 있습니다.
  • 특징: 폰은 월드에 배치되며, 변환 정보를 가집니다. ACharacter는 자체적으로 UCharacterMovementComponent를 포함하여 복잡한 이동을 쉽게 처리할 수 있습니다.
  • 활용: 플레이어 캐릭터, 적 AI, 차량, 비행기 등 게임 내에서 플레이어 또는 AI에 의해 움직이거나 상호작용할 수 있는 모든 대상을 만들 때 사용됩니다.

UActorComponent / USceneComponent

  • 역할: UActorComponent는 액터가 소유하고 등록하는 기능 모듈이며, USceneComponent는 UActorComponent를 상속받아 3D 공간의 위치, 회전, 스케일과 부착(Attachment) 계층을 가지는 컴포넌트입니다.
  • 특징: 액터 하나에 여러 컴포넌트를 조립해 복잡한 기능을 만들 수 있습니다. 예를 들어, UStaticMeshComponent(3D 모델), UCameraComponent(카메라 시점), UParticleSystemComponent(파티클 효과), UAudioComponent(사운드) 등이 있습니다.
  • 활용: 액터의 시각적 표현, 충돌 감지, 물리 시뮬레이션, 카메라, 사운드, 커스텀 로직 등 특정 모듈화된 기능을 구현할 때 사용됩니다.

데이터를 둘 위치

클래스 이름을 외우기보다 데이터가 어느 실행 환경에서 얼마나 오래 필요한지부터 묻습니다.

데이터의 수명과 공유 범위에 따른 위치

각 클래스의 대표 책임과 자동으로 보장하지 않는 범위를 비교합니다.

데이터의 수명과 공유 범위에 따른 위치
데이터 예둘 위치수명·공유 범위
레벨 간 선택값GameInstance같은 게임 인스턴스에서 유지; 복제·디스크 저장은 별도
승리 규칙GameMode서버 권한에서 판단; 원격 클라이언트에 인스턴스 복제 안 함
현재 라운드GameState클라이언트에 공유할 상태; 사용자 정의 필드는 복제 설정 필요
플레이어별 점수PlayerState해당 플레이어의 공유할 상태; Pawn 재생성과 분리 가능
로컬 입력·UIPlayerController로컬 플레이어의 처리와 서버 측 제어를 구분
몸체·개별 기능Pawn·컴포넌트스폰·파괴되는 월드 대상의 수명에 맞춰 관리
레벨 간 선택값
둘 위치: GameInstance
수명·공유 범위: 같은 게임 인스턴스에서 유지; 복제·디스크 저장은 별도
승리 규칙
둘 위치: GameMode
수명·공유 범위: 서버 권한에서 판단; 원격 클라이언트에 인스턴스 복제 안 함
현재 라운드
둘 위치: GameState
수명·공유 범위: 클라이언트에 공유할 상태; 사용자 정의 필드는 복제 설정 필요
플레이어별 점수
둘 위치: PlayerState
수명·공유 범위: 해당 플레이어의 공유할 상태; Pawn 재생성과 분리 가능
로컬 입력·UI
둘 위치: PlayerController
수명·공유 범위: 로컬 플레이어의 처리와 서버 측 제어를 구분
몸체·개별 기능
둘 위치: Pawn·컴포넌트
수명·공유 범위: 스폰·파괴되는 월드 대상의 수명에 맞춰 관리

이 표는 데이터 배치의 예입니다. 실제 복제 조건과 이동·재접속 시 보존 정책은 게임이 명시해야 합니다.

월드의 액터 참조를 장수 객체에 보관하더라도 액터의 생존이 연장되는 것은 아닙니다. 타이머와 델리게이트 등은 EndPlay를 비롯한 적절한 수명 경계에서 해제하고, 이후 사용할 참조의 유효성을 확인합니다.

다음 장에서는 APawn, ACharacter, AController의 역할과 구현을 이어갑니다.