1. GameplayCueManager

image.png

image.png

image.png

image.png

image.png

image.png

#pragma once

#include "CoreMinimal.h"
#include "GameFeatureAction.h"
#include "GameFeatureAction_AddGameplayCuePath.generated.h"

// WorldActionBase를 상속받지 않음 -> 모든 월드에서 알고 있어야 하기 때문
UCLASS()
class UGameFeatureAction_AddGameplayCuePath : public UGameFeatureAction
{
	GENERATED_BODY()
public:
	UGameFeatureAction_AddGameplayCuePath();

	// GameplayCueNotify 에셋 경로 추가
	UPROPERTY(EditAnywhere, Category="GameFeature|GameplayCue")
	TArray<FDirectoryPath> DirectoryPathsToAdd;
};
#include "GameFeatureAction_AddGameplayCuePath.h"

UGameFeatureAction_AddGameplayCuePath::UGameFeatureAction_AddGameplayCuePath()
	: Super()
{
	// Lyra에서는 해당 폴더에서 모든 GameplayCue를 관리함
	// 우리의 경우 Weapon 폴더를 등록시키면 됨
	DirectoryPathsToAdd.Add(FDirectoryPath{TEXT("/GameplayCues")});
}

#pragma once

#include "GameFeatureStateChangeObserver.h"
#include "GameFeaturesProjectPolicies.h"
#include "LyraGameFeaturePolicy.generated.h"

UCLASS()
class ULyraGameplayFeaturePolicy : public UDefaultGameFeaturesProjectPolicies
{
	GENERATED_BODY()

public:
	ULyraGameplayFeaturePolicy(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
	
	/**
	 * GameFeaturesProjectPolicies Interfaces
	 */
	virtual void InitGameFeatureManager() override;
	virtual void ShutdownGameFeatureManager() override;

	// Observer로 등록한 객체 관리
	// 아래 AddGameplayCuePaths가 한 예시
	UPROPERTY(Transient)
	TArray<TObjectPtr<UObject>> Observers;
};

UCLASS()
class ULyraGameFeature_AddGameplayCuePaths : public UObject, public IGameFeatureStateChangeObserver
{
	GENERATED_BODY()

public:
	/**
	 * IGameFeatureStateChangeObserver Interfaces
	 */
	virtual void OnGameFeatureRegistering(const UGameFeatureData* GameFeatureData, const FString& PluginName, const FString& PluginURL) override;
	virtual void OnGameFeatureUnregistering(const UGameFeatureData* GameFeatureData, const FString& PluginName, const FString& PluginURL) override;
};

ULyraGameplayFeaturePolicy::ULyraGameplayFeaturePolicy(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
}

void ULyraGameplayFeaturePolicy::InitGameFeatureManager()
{
	Observers.Add(NewObject<ULyraGameFeature_AddGameplayCuePaths>());

	UGameFeaturesSubsystem& Subsystem = UGameFeaturesSubsystem::Get();
	for(UObject* Observer : Observers)
	{
		Subsystem.AddObserver(Observer);
	}

	// 위에서 Observer를 등록했으므로, GameFeatureManager가 초기화되는 과정에 반영됨
	Super::InitGameFeatureManager();
}

void ULyraGameplayFeaturePolicy::ShutdownGameFeatureManager()
{
	Super::ShutdownGameFeatureManager();

	UGameFeaturesSubsystem& Subsystem = UGameFeaturesSubsystem::Get();
	for(UObject* Observer : Observers)
	{
		Subsystem.RemoveObserver(Observer);
	}
}

image.png