MassTrait 정의
엔티티의 초기 구성을 선언하는 Trait 시스템을 이해하고 커스텀 Trait를 작성합니다
Trait의 역할
Fragment와 Tag의 초기화 조합을 정의하는 설계 단위
Trait은 엔티티가 생성될 때 어떤 Fragment/Tag를 포함하고 어떤 초기값을 가질지를 정의합니다. Blueprint의 Component 추가와 유사하지만, ECS 방식으로 동작합니다.
Trait는 단순한 Fragment 목록이 아닙니다. BuildTemplate 메서드에서 Fragment 추가, Tag 설정, 기본값 할당, 다른 Trait 의존성 처리까지 담당합니다.
// UMassEntityTraitBase를 상속하여 커스텀 Trait 정의
UCLASS()
class UHealthTrait : public UMassEntityTraitBase
{
GENERATED_BODY()
public:
// 에디터에서 설정 가능한 기본값
UPROPERTY(EditAnywhere, Category = "Health")
float DefaultHealth = 100.0f;
UPROPERTY(EditAnywhere, Category = "Health")
float DefaultMaxHealth = 100.0f;
protected:
// 엔티티 템플릿 빌드 시 호출됨
virtual void BuildTemplate(
FMassEntityTemplateBuildContext& BuildContext,
const UWorld& World) const override;
};
// 구현
void UHealthTrait::BuildTemplate(
FMassEntityTemplateBuildContext& BuildContext,
const UWorld& World) const
{
// Fragment 추가 및 초기값 설정
BuildContext.AddFragment<FHealthFragment>();
// 초기값 설정을 위한 콜백 등록
BuildContext.GetMutableObjectFragmentInitializers()
.Add([=](UObject& Owner, FMassEntityView& EntityView,
const EMassTranslationDirection CurrentDirection)
{
FHealthFragment& Health =
EntityView.GetFragmentData<FHealthFragment>();
Health.Current = DefaultHealth;
Health.Max = DefaultMaxHealth;
});
}
Tag Trait 작성
Tag를 추가하는 간단한 Trait 패턴
// 좀비 태그 Trait
UCLASS()
class UZombieTrait : public UMassEntityTraitBase
{
GENERATED_BODY()
protected:
virtual void BuildTemplate(
FMassEntityTemplateBuildContext& BuildContext,
const UWorld& World) const override
{
// Tag만 추가하는 가장 간단한 형태
BuildContext.AddTag<FZombieTag>();
}
};
// 전투 가능 Trait: Fragment + Tag 조합
UCLASS()
class UCombatantTrait : public UMassEntityTraitBase
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere)
float AttackDamage = 15.0f;
UPROPERTY(EditAnywhere)
float AttackRange = 200.0f;
protected:
virtual void BuildTemplate(
FMassEntityTemplateBuildContext& BuildContext,
const UWorld& World) const override
{
// 전투 관련 Fragment 추가
BuildContext.AddFragment<FCombatFragment>();
BuildContext.AddTag<FCombatantTag>();
// SharedFragment로 공유 설정 등록
FMassEntityManager& EM = UMassEntitySubsystem::
GetEntityManager(&World);
FCombatConfigSharedFragment Config;
Config.AttackDamage = AttackDamage;
Config.AttackRange = AttackRange;
uint32 Hash = UE::StructUtils::
GetStructCrc32(FConstStructView::Make(Config));
BuildContext.AddSharedFragment(
FConstSharedStruct::Make(Config));
}
};
Trait 의존성
Trait 간 의존 관계를 관리하는 방법
Trait가 다른 Trait의 Fragment에 의존하는 경우, 의존성 선언이 필요합니다. 이를 통해 빌드 순서가 올바르게 결정됩니다.
UCLASS()
class URegenTrait : public UMassEntityTraitBase
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere)
float RegenPerSecond = 5.0f;
protected:
virtual void BuildTemplate(
FMassEntityTemplateBuildContext& BuildContext,
const UWorld& World) const override
{
// 재생 Fragment 추가
BuildContext.AddFragment<FRegenFragment>();
// HealthFragment에 의존한다고 선언
// → HealthTrait가 먼저 빌드되어야 함
BuildContext.RequireFragment<FHealthFragment>();
}
// 이 Trait 이전에 빌드되어야 하는 Trait 목록
virtual void ValidateTemplate(
FMassEntityTemplateBuildContext& BuildContext,
const UWorld& World) const override
{
// HealthFragment가 템플릿에 없으면 경고
if (!BuildContext.HasFragment<FHealthFragment>())
{
UE_LOG(LogMass, Warning,
TEXT("RegenTrait requires HealthTrait!"));
}
}
};
하나의 Trait는 하나의 기능 단위를 담당하세요. HealthTrait, MovementTrait, CombatTrait처럼 분리하면 재사용성이 높아지고, MassEntityConfig에서 조합하기 편리합니다.
빌트인 Trait 목록
MassGameplay가 제공하는 주요 Trait
| Trait | 모듈 | 추가하는 Fragment/Tag |
|---|---|---|
| UMassAssortedFragmentsTrait | MassEntity | 다양한 Fragment를 에디터에서 추가 |
| UMassVisualizationTrait | MassRepresentation | ISM, Actor 표현 Fragment |
| UMassMovementTrait | MassMovement | Velocity, Force Fragment |
| UMassStateTreeTrait | MassAI | StateTree 관련 Fragment |
| UMassNavigationTrait | MassNavigation | 내비게이션 Fragment |
| UMassAvoidanceTrait | MassNavigation | 충돌 회피 Fragment |
| UMassLODCollectorTrait | MassLOD | LOD 데이터 수집 Fragment |
| UMassSmartObjectTrait | MassSmartObjects | SmartObject 상호작용 Fragment |
핵심 요약
- Trait(UMassEntityTraitBase)은 엔티티 생성 시 Fragment/Tag 추가와 초기값 설정을 담당한다
- BuildTemplate 메서드에서 AddFragment, AddTag, 초기화 콜백을 등록한다
- RequireFragment과 ValidateTemplate로 Trait 간 의존성을 선언하고 검증한다
- SharedFragment를 통해 여러 엔티티가 공유하는 설정 데이터를 효율적으로 관리한다
- 하나의 Trait는 하나의 기능 단위를 담당하도록 설계하여 재사용성을 높인다
- MassGameplay는 Visualization, Movement, StateTree, Navigation 등 다양한 빌트인 Trait을 제공한다
도전 과제
배운 내용을 직접 실습해보세요
UMassEntityTraitBase를 상속받아 커스텀 Trait을 만드세요. BuildTemplate에서 AddFragment로 FHealthFragment와 FTeamFragment를 추가하고, 초기값을 설정하는 로직을 구현하세요.
ValidateTemplate을 오버라이드하여 Trait이 요구하는 다른 Trait/Fragment가 누락되었을 때 경고를 출력하세요. 예: CombatTrait은 반드시 HealthTrait이 함께 있어야 한다는 조건을 검증하세요.
보행자(TransformTrait + MovementTrait + NavigationTrait), 차량(TransformTrait + VehicleTrait + TrafficTrait) 등 여러 Trait 조합으로 서로 다른 엔티티 타입을 설계하세요.