모드 모듈
모드 모듈은 SML이 제공하는 시스템으로, 새티스팩토리 모딩에 중요한 주요 위치에서 엔진 생명주기에 간단하게 후킹할 수 있도록 합니다.
이것은 모드 파일에서 모드 모듈 클래스를 생성하여 이루어지며, 이 클래스는 SML에 의해 적절한 시점에 자동으로 로드됩니다.
이 클래스의 인스턴스와 함수는 해당 생명주기 위치에 도달했을 때 자동으로 호출됩니다.
이 시스템은 모더에게 콘텐츠 초기화에 대한 더 많은 제어를 제공합니다. 또한 모드 간 상호작용을 수행하는 데 유용합니다.
현재 3가지 유형의 모드 모듈이 있습니다:
-
게임 인스턴스 할당 모듈(
UGameInstanceModule
), 게임이 시작될 때 한 번 호출되며, 게임이 종료될 때까지 존재합니다. -
메뉴 월드 모듈(
UMenuWorldModule
), 메인 메뉴가 로드될 때마다 한 번 호출됩니다. -
게임 월드 모듈(
UGameWorldModule
), 저장이 로드될 때마다 한 번 호출됩니다.
각 유형에 대한 자세한 내용은 아래 섹션에서 확인할 수 있습니다.
모듈은 실제로 액터가 아니지만, 메뉴 월드 및 게임 월드 모듈은 월드 컨텍스트에 접근할 수 있습니다.
플레이어가 게임을 시작하고, 메인 메뉴에서 저장 파일을 로드하고, 메인 메뉴로 돌아가고, 게임을 종료하는 경우, 다음과 같은 순서로 발생합니다:
실행 순서 시연:
(애플리케이션 열기)
1. 게임 인스턴스 할당 모듈 생성
2. 메뉴 월드 모듈 생성
(메인 메뉴에서 저장 파일 로드)
3. 메뉴 월드 모듈 파괴
4. 게임 월드 모듈 생성
(게임에서 메인 메뉴로 돌아가기)
5. 게임 월드 모듈 파괴
6. 메뉴 월드 모듈 생성
(메인 메뉴에서 애플리케이션 종료)
7. 메뉴 월드 모듈 파괴
8. 게임 인스턴스 할당 모듈 파괴
모듈 탐색
SML은 각 로드된 모드에 대한 모드 모듈을 자동으로 발견할 수 있습니다.
이러한 모듈 중 하나를 사용하려면, 해당 모듈 클래스에서 파생된 액터 또는 C++ 클래스를 생성하고 "루트 모듈" 불리언 값을 true로 설정하면 됩니다.
모듈에 부여하는 실제 클래스 이름은 중요하지 않지만, 일관성과 충돌 보고서에서의 식별을 위해 제안된 이름을 사용하는 것이 좋습니다. 모든 모드는 각 유형(게임 인스턴스, 메뉴 월드, 게임 월드)에 대해 정확히 하나의 루트 모듈을 가질 수 있으며, 이 모듈은 이름에 관계없이 자동으로 등록되고 부트스트랩됩니다.
각 유형의 루트 모듈은 정확히 하나 만 있어야 합니다. 그렇지 않으면 SML은 이 실수를 경고하기 위해 게임을 고의로 충돌시킵니다. |
생명주기 이벤트 전송
DispatchLifecycleEvent
는 모든 모드 모듈이 오버라이드 할 수 있는 함수입니다.
이벤트는 주어진 "생명주기 위치"의 다양한 단계에서 호출됩니다.
각 "생명주기 위치"는 다음 3단계로 구성됩니다:
-
생성
-
초기화
-
초기화 후
(ELifecyclePhase
열거형으로 구분됨)
이 함수를 재정의할 때는 switch 문을 사용하여 다양한 단계를 구분하고 맞춤 초기화 논리를 수행할 수 있습니다.
모듈 유형
모드 모듈에 모드의 모드 참조를 포함하는 이름을 부여하는 것이 좋습니다. 이것은 여러 모드를 에디터에서 로드할 때 어떤 모듈이 어떤 모드에 속하는지 알 수 있도록 도와주며, 충돌 로그에서 식별하기 쉽게 만듭니다.
게임 인스턴스 할당 모듈(UGameInstanceModule
)
제안된 루트 모듈 이름: RootInstance_모드참조
제안된 하위 모듈 이름: SubInstance_MoreDetails_모드참조
게임 인스턴스 모듈은 게임 인스턴스에 할당되어 있으며 게임이 종료될 때까지 존재합니다. 이는 궁극적으로 게임 세션당 한 번 호출됩니다. 이 모듈이 다시 호출되려면 새티스팩토리를 다시 시작해야 합니다. 이 모듈은 월드를 다시 불러와도 지속되며 월드 컨텍스트 없이 접근할 수 있습니다.
또한 이 시점에서 등록해야 할 수 있는 몇 가지 표준 처리를 제공합니다:
-
전역 아이템 툴팁 제공자
이들은 클래스의 생성자에서 주어진 변수에 클래스를 추가하거나, 블루프린트를 사용하는 경우 액터의 기본값에 추가하여 등록할 수 있습니다.
이 모듈은 또한 GetGameInstance
함수를 제공하여
모듈을 트리거하는 게임 인스턴스를 가져올 수 있습니다.
이 기능을 맞춤 생명주기 이벤트 처리에 사용할 수 있습니다.
메뉴 월드 모듈(UMenuWorldModule
)
제안된 루트 모듈 이름: RootMenuWorld_모드참조
제안된 하위 모듈 이름: SubMenuWorld_MoreDetails_모드참조
메뉴 월드 모듈은 메인 메뉴 월드에 연결되어 있으며 종료될 때까지 존재합니다.
이 모듈은 일반적으로 메인 메뉴에서 초기화해야 하는 것들에 사용됩니다. 메인 메뉴 장면에 메뉴 버튼과 같은 것을 추가하려면 이곳이 적합합니다.
사용자가 저장을 종료한 후 메인 메뉴로 돌아가면, 이 모듈이 다시 호출됩니다.
게임 월드 모듈(UGameWorldModule
)
제안된 루트 모듈 이름: RootGameWorld_모드참조
제안된 하위 모듈 이름: SubGameWorld_MoreDetails_모드참조
게임 월드 모듈은 사용자가 새티스팩토리를 플레이하는 일반 게임 월드에 연결되어 있습니다. 이 모듈은 저장이 로드될 때부터 저장이 종료되거나 다른 저장이 로드될 때까지 존재합니다.
이 모듈은 사용자가 실제로 게임을 플레이하는 모든 저장 또는 월드의 로드 단계에서 초기화해야 하는 것들에 이상적입니다.
사용자가 저장 파일(자동 저장 포함)을 로드하면 이 모듈이 다시 호출됩니다.
이 모듈은 또한 이 시점에서 등록해야할 수 있는 몇 가지 표준 처리를 제공합니다:
-
도면
-
M.A.M. 연구 트리
이들은 클래스의 생성자에서 주어진 변수에 클래스를 추가하여 등록할 수 있습니다.
하위 모듈
각 3가지 모듈 유형(게임 인스턴스, 메뉴 월드, 게임 월드)의 여러 모듈을 생성할 수 있습니다. 예를 들어, 2개의 게임 월드 모듈, 1개의 게임 인스턴스 모듈, 1개의 메뉴 월드 모듈을 가질 수 있습니다.
유형의 여러 모듈을 가지려면, 루트 모듈이 다른 모듈을 호출해야 합니다. 이 예에서는 1개의 메뉴 월드 모듈이 루트로 표시되고, 1개의 게임 인스턴스 모듈이 루트로 표시되며, 1개의 게임 월드 모듈이 루트로 표시되어 두 번째(비루트) 게임 월드 모듈을 호출합니다.
ExampleMod는 이 예를 루트 게임 월드 모듈에서 보여줍니다.
SpawnChildModule을 통해 모듈이 생성되면, 부모 모듈이 이미 수신한 모든 단계를 수신합니다. ExampleMod 예제에서 자식 모듈은 초기화 단계에서 생성됩니다. 자식 모듈은 부모보다 늦게 생성되지만 여전히 생성 단계가 호출됩니다.
모드 간 상호작용을 위한 모듈 사용
모듈은 조건부로 로드되는 하위 모듈을 가질 수 있으며, 예를 들어 구성 기반 콘텐츠 등록을 구현하는 데 사용될 수 있으며, 단일 모드 내에서 모듈성을 허용합니다.
각 모드의 루트 모드 모듈은 다른 모드에서 모드 참조를 통해 접근할 수 있습니다. 이것은 효율적으로 크로스 모드 통합을 수행하는 데 사용될 수 있습니다. 예를 들어, CoolCounterMod 모드가 로드될 때마다 루트 모듈 내에서 확인하고, 그런 다음 하위 모듈 "CoolCounterModIntegration"을 로드하여 CoolCounterMod에 직접 접근할 수 있습니다(모드가 존재하지 않으면 하위 모듈이 등록되지 않습니다).
블루프린트에서는 모드 참조를 통해 어떤 모드의 모드 모듈을 검색할 수 있으며,
Get WorldModuleManager
또는 Get GameInstanceModuleManager
(모듈 유형에 따라) 및 Find Module
노드를 사용하여
그런 다음 출력을 특정 모듈 클래스로 형변환할 수 있습니다.