总览
Mass 不是只有逐帧 Processor。实体组成变化、Fragment 添加移除、Tag 切换、延迟唤醒,都需要事件式机制。UMassObserverProcessor 用来观察实体操作,适合“某个 Fragment/Tag 被添加后初始化数据”或“某个状态退出后清理”。UMassSignalSubsystem 用来给实体发信号,适合“等待几秒后继续”“外部事件唤醒某批实体”。
Observer 和 Signal 的关键区别是触发源不同:Observer 监听结构变化,Signal 监听显式信号。前者适合生命周期钩子,后者适合行为流。
源码依据
MassObserverProcessor.h 中 UMassObserverProcessor 提供 ObservedTypes 和 ObservedOperations。UE5.8 里 ObservedTypes 支持多个类型,旧的 ObservedType 已 deprecated。FMassObserverExecutionContext 可通过 ExecutionContext.GetAuxData() 取得观察到的操作和类型。MassSignalSubsystem.h 中 UMassSignalSubsystem 提供 SignalEntity、SignalEntities、DelaySignalEntity、DelaySignalEntities,也有通过 command buffer 的 deferred 版本。
架构分析
Observer 最适合做“状态进入初始化”。例如给实体添加 FShopperNeedsQueueTag 后,Observer 查询队列子系统,为实体分配排队槽位,并写入 FShopperQueueFragment。如果后来移除这个 Tag,另一个 Observer 释放队列槽位。这比每帧 Processor 检查“有没有新进入队列”的布尔字段更干净。
Signal 更像行为系统的唤醒器。比如顾客使用咖啡机后需要等待 8 秒,不必每帧 Processor 递减倒计时。你可以记录状态,然后 DelaySignalEntity(Entity, "UseFinished", 8.0f),对应 Processor 只处理收到信号的实体。这样在大规模实体里能减少无意义 Tick。
使用案例
Observer 监听 Tag 添加:
UQueueEntryObserver::UQueueEntryObserver()
{
ObservedTypes.Add(FShopperNeedsQueueTag::StaticStruct());
ObservedOperations = EMassObservedOperation::Add;
ExecutionFlags = static_cast<int32>(EProcessorExecutionFlags::Server);
}
void UQueueEntryObserver::ConfigureQueries(const TSharedRef<FMassEntityManager>& EntityManager)
{
EntityQuery.AddRequirement<FShopperQueueFragment>(EMassFragmentAccess::ReadWrite);
EntityQuery.AddTagRequirement<FShopperNeedsQueueTag>(EMassFragmentPresence::All);
EntityQuery.RegisterWithProcessor(*this);
}
Signal 处理延迟行为:
SignalSubsystem.DelaySignalEntity(
UE::Mass::Signals::UseSmartObjectFinished,
Entity,
UseDuration);
项目可以把信号名集中定义,避免字符串分散。收到信号的 Processor 再检查实体状态是否仍然有效,因为延迟期间实体可能已经离开、销毁或改道。
项目落地
事件链建议保持短。一个 Observer 最多做初始化和少量 Defer,不要在 Observer 里触发复杂业务树。复杂行为仍应回到 StateTree 或 Processor。Signal 也要有命名规范,例如 Crowd.Queue.Ready、Crowd.SmartObject.Finished、Crowd.Exit.Timeout,并在调试面板里记录最近信号,排查延迟唤醒很有用。
常见坑
不要把 Observer 当每帧逻辑入口,它只响应结构变化。不要给大量实体每帧发 Signal,这会变成更难追踪的 Tick。不要假设延迟 Signal 到达时实体还在原状态。不要在 Observer 中立即做大量结构变更导致连锁触发,必要时分阶段 Defer。
源码路径索引
MassEntity/Public/MassObserverProcessor.hMassEntity/Public/MassObserverManager.hMassSignals/Public/MassSignalSubsystem.hMassEntity/Public/MassCommandBuffer.h