언리얼5와 언리얼 c++ 문법 공부를 본격적으로 시작하기 위해 Lyra Sample Game 프로젝트를 공부해보기로 했다.
샘플이래서 좀 쉬울 줄 알았다.
중간에 이것저것 다른 거 한 시간이 있긴 하지만 한달 넘게 보고 있는데 잘 이해가 안된다...
프로젝트를 처음 열었을 때 게임 모드와 디폴트 폰 등이 비어있어서 당황했다.
게임 모드는 프로젝트 세팅을 통해 LyraGameMode
로 지정되어 있었지만 디폴트 폰 등 다른 세부사항은 게임 모드가 아닌 Experience에 위임되어 있었다.
라이라 게임에선 깃발 뺏기나 탑다운 모드 등 여러 가지의 게임 종류가 있었는데 게임 종류마다 Experience
를 통해 세부사항을 세팅한다.
이런 방식은 모듈형 게임플레이(Modular gameplay)라는 방식을 라이라 게임에서 변형한 구조인 것 같다.
모듈형 게임플레이에 대해선 따로 공부.
보고 도움됐던 영상 자료들 -
https://www.youtube.com/watch?v=-DLeHXrGPrM
https://www.youtube.com/watch?v=0lEr62LQFpk
다음은 언리얼 엔진이 실행되는 게임 흐름 개요를 기반으로 내가 이해한 라이라 게임이 실행되는 (주로 Experience가 로드 되는) 흐름을 정리한 것이다.
Init()
LyraGameInstance
::Init()
:UGameFrameworkComponentManager
를 통해 필요한 초기화 스테이트(InitState)
를 등록함. 등록된 모든 피처가 어떤 단계인지 알려주는 역할이라고 이해함. Start()
가 호출된 후, 게임인스턴스의 StartGameInstance()
호출됨.게임 모드 - ALyraGameMode
::
InitGame()
:
SetTimerForNextTick
로 다음 프레임에 HandleMatchAssignmentIfNotExpectingOne
함수 호출.HandleMatchAssignmentIfNotExpectingOne()
:
OnMatchAssignmentGiven
함수를 호출함. OnMatchAssignmentGiven
(ExperienceId
, ) :ExperienceIdSource
ULyraExperienceManagerComponent
를 가져와서 SetCurrentExperience
(ExperienceId
)를 호출해 Experience 등록 시작.ULyraExperienceManagerComponent
::
SetCurrentExperience
(ExperienceId
):
ULyraAssetManager
로 ExperienceId
로부터 Experience의 경로 추출.CurrentExperience
로 지정.StartExperienceLoad
함수를 호출해서 Experience 로드 시작.StartExperienceLoad()
:
ULyraAssetManager
로 Experience에서 필요한 에셋들 비동기적(아마두)으로 로드. OnExperienceLoadComplete
함수 호출.OnExperienceLoadComplete()
:
ActionSet
이 필요한 게임 피처 플러그인의 URL 목록 만듬.UGameFeaturesSubsystem
라는 서브시스템을 통해 이 플러그인들 활성화.OnExperienceFullLoadCompleted
호출.ULyraExperienceManagerComponent
::OnExperienceFullLoadCompleted()
:
ActionList
, 즉 실행할 액션 목록을 등록하고 활성화 시작.ActionSet
에 등록되어 있는 액션들도 마찬가지로 등록 및 활성화.OnExperienceLoaded_HighPriority
, OnExperienceLoaded
, OnExperienceLoaded_LowPriority
델리게이트를 차례대로 수행. ALyraGameMode
::
InitGameState()
:
ULyraExperienceManagerComponent
의 OnExperienceLoaded
에 OnExperienceLoaded
함수 등록.OnExperienceLoaded
(CurrentExperience
) :
SpawnDefaultPawnAtTransform
를 오버라이딩해서 등록된 Experience의 DefaultPawn
을 참고하게 함.이후 레벨에 있는 모든 액터에 대해 한차례 PreInitializeComponents()
가 호출되고 이후 각 액터에 대해 InitializeComponents()
, PostInitializeComponents()
가 연속적으로 호출됨. (맞나?)
월드, 액터들의 BeginPlay()
시작. 이후 Tick()
루프 시작됨.
위 흐름은 https://ikrima.dev/ue4guide/gameplay-programming/master-engine-flow/master-engine-flow/ 기반으로 적었다.
언리얼 c++ 쪽은 거의 제로베이스인 채로 코드 읽기를 시작해서 틀린 부분이 많을테니 호옥시 이 글 읽는 분 있는 분 있으면 지적 부탁드립니당.