核心概念
复习ECS
ECS三剑客
- Component:数据组件,存储游戏状态
- Entity:实体,数据组件的载体
- System:系统,实现游戏规则、行为
完美诠释了:组合优于继承
Mass中的ECS
FMassEntityHandle
ECS中的E。用来唯一标识一个Entity实体的句柄。
// A handle to a lightweight entity. An entity is used in conjunction with the FMassEntityManager
// for the current world and can contain lightweight fragments.
USTRUCT()
struct FMassEntityHandle
{
GENERATED_BODY()
FMassEntityHandle() = default;
FMassEntityHandle(const int32 InIndex, const int32 InSerialNumber)
: Index(InIndex), SerialNumber(InSerialNumber)
{
}
UPROPERTY(VisibleAnywhere, Category = "Mass|Debug", Transient)
int32 Index = 0;
UPROPERTY(VisibleAnywhere, Category = "Mass|Debug", Transient)
int32 SerialNumber = 0;
// ...
}
FMassFragment
ECS中的C。一个数据片段,代表了一个最小数据单元。Fragment分三大类:FMassFragment、FMassSharedFragment、FMassChunkFragment。FMassSharedFragment通常用于配制常量参数上。
// This is the base class for all lightweight fragments
USTRUCT()
struct FMassFragment
{
GENERATED_BODY()
FMassFragment() {}
};
USTRUCT()
struct FMassChunkFragment
{
GENERATED_BODY()
FMassChunkFragment() {}
};
USTRUCT()
struct FMassSharedFragment
{
GENERATED_BODY()
FMassSharedFragment() {}
};
FMassTag
可理解为ECS中特殊的C。用作:标签、状态标记、分类。
// This is the base class for types that will only be tested for presence/absence, i.e. Tags.
// Subclasses should never contain any member properties.
USTRUCT()
struct FMassTag
{
GENERATED_BODY()
FMassTag() {}
};
UMassProcessor
ECS中的S。游戏逻辑写在这里。下面对一些关键成员变量进行解释:
- bAutoRegisterWithProcessingPhases表示是否自动注册到对应执行阶段。一般在父类Processor中会关掉自动注册,在子类中才开启自动注册。
- bRequiresGameThreadExecution表示Processor是否要求在游戏主线程中执行,默认值是false,即允许在其他线程执行。Processor中涉及到调用Actor的一些线程敏感函数的时候可以开启这个选项。
- ExecutionFlags是用来控制Processor是否在服务器、客户端、单机上执行。
- ProcessingPhase控制执行所处的阶段(PrePhysics、StartPhysics、DuringPhysics、EndPhysics、PostPhysics、FrameEnd)。
- ExecutionOrder是用来控制Processor之间执行的先后顺序的。比如A Processor要在B Processor后面执行,但是又要在C Processor前面执行。
UMassProcessor源码
UCLASS(abstract, EditInlineNew, CollapseCategories, config = Mass, defaultconfig, ConfigDoNotCheckDefaults)
class MASSENTITY_API UMassProcessor : public UObject
{
GENERATED_BODY()
public:
UMassProcessor();
UMassProcessor(const FObjectInitializer& ObjectInitializer);
/** Whether this processor should be executed on StandAlone or Server or Client */
UPROPERTY(EditAnywhere, Category = "Pipeline", meta = (Bitmask, BitmaskEnum = "/Script/MassEntity.EProcessorExecutionFlags"), config)
int32 ExecutionFlags;
/** Processing phase this processor will be automatically run as part of. */
UPROPERTY(EditDefaultsOnly, Category = Processor, config)
EMassProcessingPhase ProcessingPhase = EMassProcessingPhase::PrePhysics;
/** Configures when this given processor can be executed in relation to other processors and processing groups, within its processing phase. */
UPROPERTY(EditDefaultsOnly, Category = Processor, config)
FMassProcessorExecutionOrder ExecutionOrder;
/** Configures whether this processor should be automatically included in the global list of processors executed every tick (see ProcessingPhase and ExecutionOrder). */
UPROPERTY(EditDefaultsOnly, Category = Processor, config)
bool bAutoRegisterWithProcessingPhases = true;
UPROPERTY(EditDefaultsOnly, Category = Processor, config)
bool bRequiresGameThreadExecution = false;
};
FMassEntityQuery
FMassEntityQuery主要是用来指明Processor的执行条件,可理解为过滤器。例如,要求执行的实体必须有某一些数据片段但不能有某一个标记。
示例代码:
void UMassDebugCrowdVisualizationProcessor::ConfigureQueries()
{
EntityQuery.AddTagRequirement<FMassCrowdTag>(EMassFragmentPresence::All);
EntityQuery.AddRequirement<FTransformFragment>(EMassFragmentAccess::ReadOnly);
EntityQuery.AddRequirement<FMassRepresentationFragment>(EMassFragmentAccess::ReadWrite);
EntityQuery.AddRequirement<FMassActorFragment>(EMassFragmentAccess::ReadWrite);
EntityQuery.RequireMutatingWorldAccess(); // due to UWorld mutable access
}
ObserverProcessor
一类特殊的Processor。主要是用来监听Entity上Fragment的变化。例如,某一个实体上动态添加了一个数据片段,会把所有监听此种变化ObserverProcessor都执行一遍。需要注意的是前面提到的控制参数ExecutionOrder、ProcessingPhase对ObserverProcessor无效。
/**
* Processor to stop and uninitialize StateTrees on entities.
*/
UCLASS()
class MASSAIBEHAVIOR_API UMassStateTreeFragmentDestructor : public UMassObserverProcessor
{
GENERATED_BODY()
public:
UMassStateTreeFragmentDestructor();
protected:
virtual void Initialize(UObject& Owner) override;
virtual void ConfigureQueries() override;
virtual void Execute(FMassEntityManager& EntityManager, FMassExecutionContext& Context) override;
FMassEntityQuery EntityQuery;
UPROPERTY(Transient)
TObjectPtr<UMassSignalSubsystem> SignalSubsystem = nullptr;
};
UMassStateTreeFragmentDestructor::UMassStateTreeFragmentDestructor()
: EntityQuery(*this)
{
ExecutionFlags = (int32)(EProcessorExecutionFlags::Standalone | EProcessorExecutionFlags::Server);
ObservedType = FMassStateTreeInstanceFragment::StaticStruct();
Operation = EMassObservedOperation::Remove;
bRequiresGameThreadExecution = true;
}
UMassSignalSubsystem
Mass中的信号系统,可理解为不带参数的事件通知。