일반적으로 많이 사용하는 Actor나 ActorComponent가 아니라, 간혹 Object를 바로 상속받거나 LocalPlayerSubsystem 같은 클래스를 상속받은 BP 클래스를 만들어서 사용해야 할 때가 있다. 그런데, 그렇게 상속받은 클래스에서 BlueprintFunctionLibrary에 정의된 함수를 호출하려고 하면 잘 안된다. 에디터에서 마우스 오른쪽을 눌러 다른 BP 함수 라이브러리의 함수를 찾아도 아예 보이지가 않는다.

 

정확한 원인은 잘 모르겠지만, BlueprintFunctionLibrary 함수를 호출할 때는 호출하려는 클래스의 GetWorld 함수 접근이 필요한데, Actor나 ActorComponent의 경우 해당 함수가 에디터에서도 접근할 수 있게 노출되어 있지만, UObject나 Subsystem 계통의 클래스들은 그게 안되어 있어서 생긴 문제로 보인다.

 

그래서, BP 클래스를 만들기 전에 부모 클래스를 c++로 만들고, Blueprintable 속성을 넣어주고, GetWorld 함수를 오버라이드하면 해결이 된다.

// MyGameSoundSubsystem.h
UCLASS(Blueprintable)
class MYGAME_API UMyGameSoundSubsystem : public ULocalPlayerSubsystem
{
    GENERATED_BODY()

public:
    virtual UWorld* GetWorld() const override;
//...
};
  
  
// MyGameSoundSubsystem.cpp
UWorld* UMyGameSoundSubsystem::GetWorld() const
{
#if WITH_EDITOR
    if (IsTemplate())
    {
        return nullptr;
    }
#endif

    return Super::GetWorld();
}

가장 간단한 방법은 위의 코드처럼 cpp 함수의 구현부에서 그냥 부모 함수만 호출해도 되긴 하는데, 에디터에서는 뭔가 또 다르게 작동하는 게 있어서 예외처리는 필요하다.

 

항상 위의 코드처럼 작성해야 하는 건 아니고 경우에 따라서는 부모 클래스나 Outer 클래스를 참조해야 할 필요도 있고, WorldContext를 명시적으로 노출해서 사용해야 하는 경우도 있다.

 

코드 출처: https://forums.unrealengine.com/t/can-you-use-a-blueprint-function-library-in-an-object-class/350918/31

 

ps. 일반적으로 Actor나 ActorComponent는 현재 맵(Level)의 월드에 귀속되지만, UObject를 상속받은 클래스 혹은 Subsystem 클래스들은 싱글턴처럼 쓰이는 경우가 많고, 현재 월드가 아닌 다른 월드(엔진 기본 월드?)에 귀속되어 있을 수 있다.

1. 바이오스 설정으로 들어가서 WOL 기능 켜기. (바이오스 제조사마다 메뉴 위치나 이름이 다름)

    Wake up on LAN이라고 명시적으로 나와 있는 제조사도 있지만,

    Powe on by PCIE 같은 이름으로 되어 있는 경우도 있다.

 

2. 장치 관리자의 네트워크 어댑터에서 랜 카드 속성을 연 다음

   고급 탭에서 Wake on Magic Packet 같은 속성이 있으면 활성화.

   전원관리 탭에서 "이 장치를 사용하여 컴퓨터의 대기 모드를 종료할 수 있음" 기능 활성화

   간혹 랜카드 자체 절전 기능 때문에 안 되는 경우가 있으니 확인 필요 (특히 인텔 랜카드)

 

3. 제어판의 전원 버튼 옵션으로 들어가서 "빠른 시작 켜기" 기능을 끄기. (이거 놓치기 쉬움)

 

4. 그리고 컴퓨터 설정은 문제가 없는데, 간혹 스위치 허브의 문제일 때도 있다.

시중에 나와 있는 대부분의 기가비트 스위치 허브는 문제가 없는데, 2.5 Gbps 혹은 10 Gbps를 지원하는 허브 중에 WOL을 제대로 지원하지 않는 경우가 있다. 정확히는 WOL이 필요로 하는 10 Mbps 속도를 지원하지 않는 경우인데, PC에 랜포트가 2개라면 WOL 전용으로 랜선을 따로 연결하거나, (랜카드가 지원하는 경우) 컴퓨터 전원이 꺼졌을 때도 1 Gbps(혹은 그 이상의 랜포트)가 계속 켜져 있도록 하면 된다. (대기 전력은 더 먹음)

'컴퓨터' 카테고리의 다른 글

윈도우 11에서 작업표시줄만 예전으로 되돌리기  (0) 2022.02.12

UGameInstanceSubsystem을 상속받은 c++ 클래스는 싱글턴처럼 하나만 생성되는 게 원칙이다.

UCLASS()
class MYGAME_API UMySubsystem : public UGameInstanceSubsystem
{
	GENERATED_BODY()
	...
};

 

서브 시스템을 가져다 쓸 때는 클래스 타입으로 검색해서 사용한다.

GetGameInstance()->GetSubsystem<UMySubsystem>()

 

그런데, 만약 c++ 클래스를 상속 받은 블루프린트 클래스를 만들어서 그걸 사용하고 싶다면 어떻게 해야 하는지 궁금해졌다. 검색해서 알아낸 방법은 다음과 같다.

 

먼저, c++의 서브시스템을 블루프린트에서 상속 받을 수 있게 Blueprintable 속성을 추가하고, ShouldCreateSubsystem 함수를 오버라이드해서 c++ 클래스의 생성은 막고 블루프린트 클래스만 생성할 수 있게 한다.

// MySubsystem.h
UCLASS(Blueprintable)
class MYGAME_API UMySubsystem : public UGameInstanceSubsystem
{
	GENERATED_BODY()
	
public:
	virtual bool ShouldCreateSubsystem(UObject* Outer) const override;
    ...
};

// MySubsystem.cpp
bool UMySubsystem::ShouldCreateSubsystem(UObject* Outer) const
{
    TArray<UClass*> ChildClasses;
    GetDerivedClasses(GetClass(), ChildClasses, false);
    return (ChildClasses.Num() == 0); // 최종 자식 클래스만 생성
}

 

에디터를 실행해서 MySubsystem을 상속 받는 BP_MySubsystem이라는 블루프린트 클래스를 생성한다.

 

일단 이렇게만 해도 에디터 플레이에서는 잘 작동한다.

 

하지만, 패키징 단계에서 해당 블루프린트 클래스에 대한 참조가 없으면 누락될 수 있으니, GameInstance에서 클래스 참조를 넣어 두자.

UCLASS(BlueprintType, Blueprintable)
class MYGAME_API UMyGameInstance : public UGameInstance
{
	GENERATED_BODY()

public:
	UPROPERTY(EditAnywhere, BlueprintReadOnly) 
	TSubclassOf<UMySubsystem> MySubsystemClass;

변수 선언은 위와 같이 하고, UMyGameInstance를 상속받은 블루프린트 클래스(예: BP_MyGameInstance)에서 MySubsystemClass 변수값에 BP_MySubsystem를 지정해 두도록 하자.

+ Recent posts