먼저 Experience 복습이 필요하다

포탈에 닿으면 연결된 맵 로딩 및 Experiece을 전환하기 위해서 만든 CommonUser 플러그인에 대해 알아보자

편집 > 플러그인 에서 CommonUser 플러그인을 볼 수 있다.
Lyra 샘플 프로젝트에서 만든 플러그인이다.
참고: 라이라 샘플 게임을 위한 언리얼 엔진의 일반 사용자 플러그인 | 언리얼 엔진 5.5 문서 | Epic Developer Community
맵 요청 시 UCommonSessionSubsystem에 전달할 오브젝트
UCLASS(BlueprintType)
class COMMONUSER_API UCommonSession_HostSessionRequest : public UObject
{
// ...
public:
/** Returns the maximum players that should actually be used, could be overridden in child classes */
virtual int32 GetMaxPlayers() const;
/** Returns the full map name that will be used during gameplay */
virtual FString GetMapName() const;
// ServerTravel에 전달할 Url 생성
virtual FString ConstructTravelURL() const;
/** Returns true if this request is valid, returns false and logs errors if it is not */
virtual bool ValidateAndLogErrors() const;
};
그렇다면 UCommonSession_HostSessionRequest을 어디서 만들까
ULyraUserFacingExperienceDefinition::CreateHostingRequest()에서 만든다.
UCommonSession_HostSessionRequest* ULyraUserFacingExperienceDefinition::CreateHostingRequest() const
{
const FString ExperienceName = ExperienceID.PrimaryAssetName.ToString();
const FString UserFacingExperienceName = GetPrimaryAssetId().PrimaryAssetName.ToString();
UCommonSession_HostSessionRequest* Result = NewObject<UCommonSession_HostSessionRequest>();
Result->OnlineMode = ECommonSessionOnlineMode::Online;
Result->bUseLobbies = true;
Result->MapID = MapID; //< 맵 id
Result->ModeNameForAdvertisement = UserFacingExperienceName;
Result->ExtraArgs = ExtraArgs;
Result->ExtraArgs.Add(TEXT("Experience"), ExperienceName); //< Experience 이름
Result->MaxPlayerCount = MaxPlayerCount;
if (bRecordReplay)
{
Result->ExtraArgs.Add(TEXT("DemoRec"), FString());
}
return Result;
}
class COMMONUSER_API UCommonSessionSubsystem : public UGameInstanceSubsystem
다른 모듈에서도 이 UCommomSessionSubSystem을 사용할 수 있게 하는 매크로
참고: 언리얼 엔진의 모듈 API 지정자 | 언리얼 엔진 5.5 문서 | Epic Developer Community
일반적인 싱글톤의 단점을 해결한 클래스
싱글톤은 게임이 실행되고 끝날 때까지 유지된다. 그래서 이전에 접속한 유저의 데이터가 남아있거나 하는 문제가 있다.
// SubSystem.h
* Currently supported Subsystem lifetimes are:
* Engine -> inherit UEngineSubsystem
* Editor -> inherit UEditorSubsystem
* GameInstance -> inherit UGameInstanceSubsystem
* World -> inherit UWorldSubsystem
* LocalPlayer -> inherit ULocalPlayerSubsystem
USubSystem은 각각의 타입(Engine, Editor, ..)에 따라 종속되는 생명주기를 가지는 것을 알 수 있다.
즉 월드A의 서브시스템은 월드A가 파괴될 때 함께 파괴된다.
참고: 프로그래밍 서브시스템 | 언리얼 엔진 5.5 문서 | Epic Developer Community
아무튼 앞에서 만든 UCommonSession_HostSessionRequest* Request로부터 Url을 생성해 ServerTravel에 전달한다.
void UCommonSessionSubsystem::HostSession(APlayerController* HostingPlayer, UCommonSession_HostSessionRequest* Request)
{
// ...
GetWorld()->ServerTravel(Request->ConstructTravelURL());
}
그래서 앞에서 설명한 동작들을 어디서 하는가 하면, 포탈 블루프린트에서 하고 있다.

ActorBeginOverlap 이벤트에서 충돌한 액터가 로컬 플레이어면

미리 설정한 Experience인 UserFacingExperienceToLoad 변수로부터 Request를 생성하 CommonSessiongSubsystem에 전달한다.