UGameInstanceSubsystem

GameInstanceÀÇ ¼­ºê ½Ã½ºÅÛÀº UGameInstanceSubsystem Ŭ·¡½º°¡ ÀÖ´Ù.
´Ù¸¥ ¼­ºê ½Ã½ºÅÛµµ ÀÖÁö¸¸ ¿©±â¼­´Â UGameInstanceSubsystem¸¸ ¾Ë¾Æ º»´Ù.

UGameInstanceSubsystem¸¦ ´ÙÀ½°ú °°ÀÌ »ó¼Ó ÇßÀ»¶§ µ¿ÀÛÀº ´ÙÀ½°ú °°´Ù.
class UMyGamesSubsystem : public UGameInstanceSubsystem

  1. UGameInstance »ý¼º ÀÌÈÄ, UMyGamesSubsystem ¶ó´Â ÀνºÅϽº ¿ª½Ã »ý¼ºµÈ´Ù.
  2. UGameInstance ÃʱâÈ­ ½Ã, ¼­ºê½Ã½ºÅÛ¿¡¼­ Initialize() °¡ È£ÃâµÈ´Ù.
  3. UGameInstance Á¾·á ½Ã, ¼­ºê½Ã½ºÅÛ¿¡¼­ Deinitialize() °¡ È£ÃâµÈ´Ù.
  4. ÀÌ ½ÃÁ¡¿¡¼­ ¼­ºê½Ã½ºÅÛ¿¡ ´ëÇÑ ÂüÁ¶°¡ »èÁ¦µÇ°í ´õÀÌ»ó ÂüÁ¶°¡ ¾øÀ¸¸é ¼­ºê½Ã½ºÅÛÀº °¡ºñÁö Ä÷º¼Ç µÈ´Ù.

¼­ºê½Ã½ºÅÛÀ» »ç¿ëÇÏ´Â ÀÌÀ¯

  • ÇÁ·Î±×·¡¹Ö ½Ã°£ÀÌ Àý¾àµÈ´Ù.
  • ¿£Áø Ŭ·¡½º ¿À¹ö¶óÀ̵带 ÇÇÇÒ ¼ö ÀÖ´Ù.
  • ÀÌ¹Ì ¹Ù»Û Ŭ·¡½º¿¡ API Ãß°¡¸¦ ÇÇÇÒ ¼ö ÀÖ´Ù.
  • »ç¿ëÀÚ¿¡°Ô Ä£¼÷ÇÑ À¯ÇüÀÇ ³ëµå¸¦ ÅëÇØ ºí·çÇÁ¸°Æ®·Î ¾×¼¼½ºÇÒ ¼ö ÀÖ´Ù.
  • ¿¡µðÅÍ ½ºÅ©¸³ÆÃÀ̳ª Å×½ºÆ® ÄÚµå ÀÛ¼ºÀ» À§ÇØ Python ½ºÅ©¸³Æ®¿¡ ¾×¼¼½ºÇÒ ¼ö ÀÖ´Ù.
  • Äڵ庣À̽ºÀÇ ¸ðµâ¼º°ú ÀÏ°ü¼ºÀ» Á¦°øÇÑ´Ù.
ÀÌÇÏ ÀÚ¼¼ÇÑ °³³ä ¼³¸í º¸´Ù´Â ÆÁÀÇ ¿¹Á¦¿¡ ´ëÇؼ­ º¸¿©ÁØ´Ù.
UGameInstanceSubsystem¸¦ »ó¼Ó¸¸ Çصµ GameInstanceÀÇ ¼­ºê·Î ÀÚµ¿À¸·Î µî·ÏÀÌ µÈ´Ù.

Á¾¼Ó ¼ø¼­ Á¤Çϱâ

UGameInstanceSubsystemÀ» »ó¼ÓÇÑ ¿©·¯°³ÀÇ Å¬·¡½º°¡ ÀÖÀ»¶§ Á¾¼Ó ¼ø¼­¸¦ Á¤ÇØ º¸ÀÚ.
Á¾¼Ó ¼ø¼­´Â Collection.InitializeDependency ÇÔ¼ö·Î Á¤ÇÑ´Ù.
MySecondInstance -> MyFirstInstance ¼ø¼­·Î »ý¼º µÇµµ·Ï ¼³Á¤ÇÏ´Â ÄÚµåÀÌ´Ù.

MyFirstInstance.h
#pragma once

#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "MyFirstInstance.generated.h"

UCLASS()
class UMGLISTVIEWDEMO_API UMyFirstInstance : public UGameInstanceSubsystem
{
    GENERATED_BODY()
   
public:
    virtual void Initialize(FSubsystemCollectionBase& Collection) override;
    virtual void Deinitialize() override;
};

MyFirstInstance.cpp
#include "MyFirstInstance.h"
#include "MySecondInstance.h"
#include "Subsystems/SubsystemCollection.h"

void UMyFirstInstance::Initialize(FSubsystemCollectionBase& Collection)
{
    Collection.InitializeDependency(UMySecondInstance::StaticClass());
    UE_LOG(LogTemp, Warning, TEXT("%s"), *FString(__FUNCTION__));
}

void UMyFirstInstance::Deinitialize()
{
    UE_LOG(LogTemp, Warning, TEXT("%s"), *FString(__FUNCTION__));
}

MySecondInstance.h
#pragma once

#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "MySecondInstance.generated.h"

UCLASS()
class UMGLISTVIEWDEMO_API UMySecondInstance : public UGameInstanceSubsystem
{
    GENERATED_BODY()
public:
    virtual void Initialize(FSubsystemCollectionBase& Collection) override;
    virtual void Deinitialize() override;
};

MySecondInstance.cpp
#include "MySecondInstance.h"

void UMySecondInstance::Initialize(FSubsystemCollectionBase& Collection)
{
    UE_LOG(LogTemp, Warning, TEXT("%s"), *FString(__FUNCTION__));
}

void UMySecondInstance::Deinitialize()
{
    UE_LOG(LogTemp, Warning, TEXT("%s"), *FString(__FUNCTION__));
}


void AUmgListViewDemoGameModeBase::StartPlay()
{
    if (GetWorld() == nullptr)
        return;
    UMyFirstInstance* FirstInstance = GetWorld()->GetGameInstance()->GetSubsystem<UMyFirstInstance>();
}

AGameModeBase¸¦ »ó¼ÓÇÑ Å¬·¡½º¿¡¼­ UMyFirstInstance Ŭ·¡½º¸¦ ¾ò¾î¿À°í ÀÖ´Ù.

UGameInstanceSubsystem »ó¼ÓÇÏ¿© °¡»ó ÇÔ¼ö »ç¿ëÇϱâ

UMySubSystem Ŭ·¡½º¸¦ »ó¼ÓÇÏ¿© °¡»ó ÇÔ¼ö·Î ¿©·¯°³ÀÇ GameInstanceSubsystemÀ» »ç¿ëÇØ º¸ÀÚ.
UGameInstanceSubsystemÀº C++ ¼ø¼ö °¡»ó ÇÔ¼ö¸¦ Áö¿øÇÏÁö ¾Ê´Â´Ù.

Ãß»ó Ŭ·¡½º·Î ´ÙÀ½°ú °°ÀÌ ÁöÁ¤ ÇÑ´Ù.
UCLASS(Abstract, Blueprintable, BlueprintType)
class UMGLISTVIEWDEMO_API UMySubSystem : public UGameInstanceSubsystem

PURE_VIRTUAL·Î ¼ø¼ö °¡»ó ÇÔ¼ö ó·³ »ç¿ëÇϱâ

MySubSystem.hÀÇ UMySubSystem Ŭ·¡½º¿¡¼­ ¼ø¼ö °¡»óÇÔ¼ö¿Í °°ÀÌ »ç¿ëÇϱâ À§Çؼ­ PURE_VIRTUAL¸¦ ¼±¾ðÇÑ´Ù.
UFUNCTION(BlueprintCallable, Category = "BaseInstance")
virtual FString GetBaseName() PURE_VIRTUAL(UMySubSystem::GetBaseName, return TEXT(""););

UMySubSystemÀ» »ó¼ÓÇѴ٠Ŭ·¡½º´Â MyInstanceOne, MyInstanceTwo°¡ ÀÖ´Ù.
PURE_VIRTUALÀ» »ó¼ÓÇÑ GetBaseNameÀº virtual, override¸¦ ºÙÀÌÁö ¾Ê¾Æµµ Àß µ¿ÀÛÇÑ´Ù.

»ó¼Ó ÇßÀ»¶§ GetBaseNameÀ» Á¤ÀÇ ÇÏÁö ¾ÊÀ¸¸é ÄÄÆÄÀÏ ¿¡·¯°¡ ¾È¶á´Ù.
GetBaseNameÀ» Á¤ÀÇ ÇÏÁö ¾ÊÀ¸¸é ·±Å¸ÀÓ¿¡ ¿¡·¯°¡ ¹ß»ýÇÑ´Ù.



±×³É °¡»ó ÇÔ¼ö·Î »ç¿ë

PURE_VIRTUAL »ç¿ë½Ã °ÔÀÓ ½ÇÇàÁß Á×´Â°Ô ½È´Ù¸é ±×³É °¡»ó ÇÔ¼ö¸¦ »ç¿ëÇØ¾ß ÇÑ´Ù.

±×³É °¡»ó ÇÔ¼ö·Î »ç¿ëÇÒ¶§´Â °¡»ó ÇÔ¼ö¸¦ ¼±¾ð ÇÏ¸é µÈ´Ù.
    UFUNCTION(BlueprintCallable, Category = "BaseInstance")
    virtual FString GetBaseName() { return TEXT("");  }

»ó¼ÓÇÑ ÀڽĿ¡¼­´Â ´ÙÀ½°ú °°ÀÌ ¼±¾ð ÇÑ´Ù.
    virtual FString GetBaseName() override
    {
        return TEXT("UMyInstanceOne");
    }

GetBaseNameÀ» ¿Àºê¶óÀÌÆà ÇÏÁö ¾Ê¾Æµµ Á×Áö ¾Ê´Â´Ù.
¿©·¯°³ÀÇ GameInstanceSubsystemÀ» ¾ò¾î ¿Ã¶§´Â GetSubsystemArray ÇÔ¼ö·Î ¾ò¾î¿Â´Ù.

UMySubSystem.h
#pragma once

#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "MySubSystem.generated.h"

//UCLASS(abstract)
UCLASS(Abstract, Blueprintable, BlueprintType)
class UMGLISTVIEWDEMO_API UMySubSystem : public UGameInstanceSubsystem
{
    GENERATED_BODY()
   
public:
    int GetValue();
    void SetValue(int v);

#if  1
    UFUNCTION(BlueprintCallable, Category = "BaseInstance")
    virtual FString GetBaseName() PURE_VIRTUAL(UMySubSystem::GetBaseName, return TEXT(""););
#else
    //±×³É °¡»ó ÇÔ¼ö·Î »ç¿ë
    UFUNCTION(BlueprintCallable, Category = "BaseInstance")
    virtual FString GetBaseName() { return TEXT("");  };
#endif

protected:
    int Value = 3;
};

UMySubSystem.cpp
#include "MySubSystem.h"

int UMySubSystem::GetValue()
{
    return Value;
}

void UMySubSystem::SetValue(int v)
{
    Value = v;
}

MyInstanceOne.h
#pragma once

#include "CoreMinimal.h"
#include "MySubSystem.h"
#include "MyInstanceOne.generated.h"

UCLASS()
class UMGLISTVIEWDEMO_API UMyInstanceOne : public UMySubSystem
{
    GENERATED_BODY()

public:
    virtual void Initialize(FSubsystemCollectionBase& Collection) override;
    virtual void Deinitialize() override;

#if  1
    FString GetBaseName()
    {
        return TEXT("UMyInstanceOne");
    }
#else
    //±×³É °¡»ó ÇÔ¼ö·Î »ç¿ë
    virtual FString GetBaseName() override
    {
        return TEXT("UMyInstanceOne");
    }
#endif
};

MyInstanceOne.cpp
#include "MyInstanceOne.h"

void UMyInstanceOne::Initialize(FSubsystemCollectionBase& Collection)
{
    UE_LOG(LogTemp, Warning, TEXT("%s"), *FString(__FUNCTION__));
}

void UMyInstanceOne::Deinitialize()
{
    UE_LOG(LogTemp, Warning, TEXT("%s"), *FString(__FUNCTION__));
}

MyInstanceTwo.h
#pragma once

#include "CoreMinimal.h"
#include "MySubSystem.h"
#include "MyInstanceTwo.generated.h"

UCLASS()
class UMGLISTVIEWDEMO_API UMyInstanceTwo : public UMySubSystem
{
    GENERATED_BODY()

public:
    virtual void Initialize(FSubsystemCollectionBase& Collection) override;
    virtual void Deinitialize() override;

#if  1
    FString GetBaseName()
    {
        return TEXT("UMyInstanceTwo");
    }
#else
    //±×³É °¡»ó ÇÔ¼ö·Î »ç¿ë
    virtual FString GetBaseName() override
    {
        return TEXT("UMyInstanceTwo");
    }
#endif
};

MyInstanceTwo.cpp
#include "MyInstanceTwo.h"

void UMyInstanceTwo::Initialize(FSubsystemCollectionBase& Collection)
{
    UE_LOG(LogTemp, Warning, TEXT("%s"), *FString(__FUNCTION__));
}

void UMyInstanceTwo::Deinitialize()
{
    UE_LOG(LogTemp, Warning, TEXT("%s"), *FString(__FUNCTION__));
}

¿©·¯°³ÀÇ ÀνºÅϽº¸¦ °¡»óÇÔ¼ö·Î ½ÇÇà
    const TArray<UMySubSystem*>& InstList = GetWorld()->GetGameInstance()->GetSubsystemArray<UMySubSystem>();
    for (UMySubSystem* Item : InstList)
    {
        FString BaseName = Item->GetBaseName();
        UE_LOG(LogTemp, Warning, TEXT("GetBaseName : %s"), *BaseName);
    }

ÂüÁ¶)
https://docs.unrealengine.com/4.26/ko/ProgrammingAndScripting/Subsystems/
https://www.brightdevelopers.com/unreal-engine-4-c-polymorphism-overview/
http://compacttutorial.blogspot.com/2015/04/unreal-engine-4-pure-virtual-functions.html
https://www.cnblogs.com/shiroe/p/14819721.html
https://jhtop0419.tistory.com/67?category=944635