Closed Eu4ng closed 1 year ago
DA_EquipmentSlotTags 편집 편의성, EquipmentSlot과 EquipmentSocket 태그 매핑을 위해 아래와 같이 구조를 변경하고 싶다. 하지만, 현재 EquipmentComponent는 EquipmentSlot을 FGameplayTag와 1대1 대응으로 설계가 되어있는데 구조 변경 시 EquipmentSlot은 장비 카테고리(FGameplayTag)와 인덱스(int32)로 구분될 것이다. 결국 EquipmentComponent를 전부 뜯어 고쳐야하는데 그럴 가치가 과연 있는가?
장점
단점
기존
UCLASS(Blueprintable, BlueprintType, Const, Meta = (DisplayName = "Equipment Slot Tags", ShortTooltip = "Equipment SlotTags for Equipment Slots"))
class THIRDPERSON_API UEquipmentSlotTags : public UDataAsset
{
GENERATED_BODY()
protected:
// Todo C++이 아니라 에디터에서 설정할 수 있는 게임플레이 태그를 제한하는 방법은 없을까?
// Todo 프로젝트에 설정된 GameplayTag에 따라 meta=(Categories="") 커스터마이징 필요
// Todo FGameplayTagContainer로 변경?
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta=(Categories="EquipmentSlot"))
TArray<FGameplayTag> All;
// Todo 프로젝트에 설정된 GameplayTag에 따라 meta=(Categories="") 커스터마이징 필요
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta=(Categories="EquipmentSlot.Active.Main"))
FGameplayTag Primary;
public:
FORCEINLINE TArray<FGameplayTag> GetAll() const { return All; }
FORCEINLINE FGameplayTag GetPrimary() const { return Primary; }
};
변경 후
//////////////////////////////////////////////////////////////////////
// Sub Equipment Category
USTRUCT(Atomic, BlueprintType, Meta = (DisplayName = "Sub Equipment Category"))
struct FSubEquipmentCategory
{
GENERATED_USTRUCT_BODY()
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta=(Categories="EquipmentSlot.Active.Sub"))
FGameplayTag Tag;
FORCEINLINE bool operator== (const FSubEquipmentCategory& Other) const
{
return Tag == Other.Tag;
}
FORCEINLINE friend uint32 GetTypeHash (const FSubEquipmentCategory& Other)
{
return GetTypeHash(Other.Tag);
}
};
//////////////////////////////////////////////////////////////////////
// Equipment Socket Tags
USTRUCT(Atomic, BlueprintType, Meta = (DisplayName = "Equipment Socket Tags"))
struct FEquipmentSocketTags
{
GENERATED_USTRUCT_BODY()
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta=(Categories="EquipmentSocket"))
TArray<FGameplayTag> Tags;
};
//////////////////////////////////////////////////////////////////////
// Equipment Slots
UCLASS(Blueprintable, BlueprintType, Const, Meta = (DisplayName = "Equipment Slot Tags", ShortTooltip = "Equipment SlotTags for Equipment Slots"))
class THIRDPERSON_API UEquipmentSlotTags : public UDataAsset
{
GENERATED_BODY()
protected:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="EquipmentSlot")
FEquipmentSocketTags Main;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="EquipmentSlot")
TMap<FSubEquipmentCategory, FEquipmentSocketTags> Sub;
public:
FORCEINLINE TArray<FGameplayTag> GetAll() const { return All; }
FORCEINLINE FGameplayTag GetPrimary() const { return Primary; }
};
다른 작업을 우선하고 싶으므로 구조 변경은 보류
주 무기 슬롯에는 총, 방패, 검, 지팡이 등 여러 무기들이 들어갈 수 있다. Equipment.Active.Main.Magician, Equipment.Active.Main.Warrior.... 처럼 직업에 따라 들 수 있는 장비를 나눌 수도 있지만 Equipment.Active.Main.Rifle, Equipment.Active.Main.Sword 처럼 장비의 종류에 따라 들 수 있는 장비를 나눌 수도 있을 것이다. 이 경우에는 장비 슬롯 별로 하나의 카테고리(태그)만 정해주면 구현이 가능하다.
하지만 게임에 따라 여러 장비를 들 수 있게 설정하거나 여러 직업을 동시에 사용할 수 있게 하고 싶을 수도 있다. 이 경우에는 장비 슬롯 별로 여러 개의 카테고리(태그)를 정해주면 구현이 가능한 대신, 데이터 애셋 설정 창이 지저분해 보일 수도 있다. 그리고 이 경우는 드물기 때문에 이 부분은 나중에 DynamicEquipmentComponent로 따로 구현하는 것이 좋을 것 같다.
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameplayTagContainer.h"
#include "UObject/Object.h"
#include "EquipmentSlots.generated.h"
/**
*
*/
//////////////////////////////////////////////////////////////////////
// Equipment Socket Tags
USTRUCT(Atomic, BlueprintType, Meta = (DisplayName = "Main Equipment Slot"))
struct FMainEquipmentSlot
{
GENERATED_USTRUCT_BODY()
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta=(Categories="EquipmentSlot.Active.Main"))
FGameplayTagContainer CategoryTags;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta=(Categories="EquipmentSocket"))
FGameplayTagContainer SocketTags;
};
//////////////////////////////////////////////////////////////////////
// Equipment Socket Tags
USTRUCT(Atomic, BlueprintType, Meta = (DisplayName = "Sub Equipment Slot"))
struct FSubEquipmentSlot
{
GENERATED_USTRUCT_BODY()
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta=(Categories="EquipmentSlot.Active.Sub"))
FName DisplayName = "DisplayName";
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta=(Categories="EquipmentSlot.Active.Sub"))
FGameplayTagContainer CategoryTags;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta=(Categories="EquipmentSocket"))
FGameplayTagContainer SocketTags;
};
//////////////////////////////////////////////////////////////////////
// Equipment Slots
UCLASS(Blueprintable, BlueprintType, Const, Meta = (DisplayName = "Equipment Slot Tags", ShortTooltip = "Equipment SlotTags for Equipment Slots"))
class THIRDPERSON_API UEquipmentSlots : public UDataAsset
{
GENERATED_BODY()
protected:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="EquipmentSlot | Main")
FMainEquipmentSlot Slot;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="EquipmentSlot | Sub", meta=(TitleProperty="{DisplayName}"))
TArray<FSubEquipmentSlot> SlotList;
public:
FORCEINLINE TArray<FGameplayTag> GetAll() const { return All; }
FORCEINLINE FGameplayTag GetPrimary() const { return Primary; }
};
EquipmentComponentBase를 EquipmentComponent, DynamicEquipmentComponent에 상속시켜 DA_EquipmentSlots의 종류에 따라 자동으로 변환시키는 방법도 좋을 것 같다.
FGameplayTagContainer 대신 TArray
를 사용하면 에디터 편집 시 가시성이 더 나은 것 같다.
목적
작업 상세 내용
문서화
Wiki - *** 참고