海量对象:编辑身份不等于 Actor 身份

自动关联目录:海量对象:编辑身份不等于 Actor 身份

核心判断:创作者需要几十万“可选择、可保存、可引用”的对象,不代表运行时需要几十万个 Actor。稳定身份属于内容模型;Actor、Component、ISM Instance 和代理只是按能力物化的 UE 表示。

一、业务冲突:全 Actor 最自然,也最容易击穿 UE 对象成本

把每个可编辑对象映射成 Actor,再把行为拆成 Component,能直接获得 Transform、层级、碰撞、复制、Tick、编辑选择和生命周期回调。早期功能少、对象少时,它显著降低开发成本。

规模上来后,成本不只在 Tick。Actor/UObject 数量会放大创建与销毁、GC 标记、Component 注册、Level Actor 管理、名称分配、委托绑定、复制扫描和调试工具遍历。即便全部关闭 Tick,几十万个空壳对象也不是免费的。

二、实际实现:逻辑拓扑已开始脱离 Actor

后续实践已经维护紧凑的对象拓扑、包围盒、组合模式和资源描述,再由空间策略决定哪些逻辑对象需要 Actor。Actor 真正生成后回报 Live;未进入需求范围的对象可以只存在于逻辑树。远距离组合还能切换为预生成代理,代理关闭碰撞和 Tick,源对象未准备好时继续保留旧表示,避免空洞。

但物化后的常规 Part 仍倾向“一逻辑对象一个 Actor/Component”。这使系统解决了“不能全常驻”,尚未完全解决“局部密集区域仍有海量 Actor”。代理以组为单位降低远景成本,却不能覆盖需要编辑、碰撞或独立状态的近景对象。

三、值得保留:表示切换已经具备正确性基础

  • 稳定逻辑 ID 不依赖 Actor 指针,Actor 可以销毁后重建。
  • 需求决策在紧凑数据上完成,不需要先 Spawn 再裁剪。
  • 代理与源对象两阶段切换,新表示未 Ready 时不隐藏旧表示。
  • 资源按唯一资产计费,共享资产不会被每个对象重复统计。
  • DS 可保留碰撞和玩法事实,同时跳过网格、材质、特效等纯呈现工作。

四、结构性缺陷:Actor/非 Actor 仍是二选一

真实对象需要的能力并不相同。静态装饰只要 Transform 和可见性;可选择对象需要编辑命中与稳定 ID;触发器需要查询形状;可破坏物需要独立状态;物理对象才需要 Body;网络对象才需要复制身份。若以最强能力的 Actor 模型承载所有对象,低能力对象会为未使用功能付费。

反过来,盲目使用 HISM 也会丢失单对象能力:实例没有独立 Actor 生命周期,材质覆盖受限,碰撞和命中映射要自建,删除会改变实例索引,复制与脚本引用也不能直接依赖索引。因此“全部实例化”与“全部 Actor 化”同样错误。

五、目标设计:能力驱动的选择性物化

内容层保存稳定 ObjectId、层级、Transform、属性块和资产引用;运行时依据能力掩码选择表示。实例索引只能是可变句柄,必须通过双向表映射稳定 ID。

能力需求推荐表示升级条件
仅静态可见ISM/HISM 或合并代理独立材质、移动、交互
可编辑但不模拟数据记录 + 编辑代理被选择或进入编辑邻域
查询/触发共享形状数据 + 查询服务需要持续 Body/Overlap
独立运动或物理Actor + PrimitiveComponent退出活跃集后可降级
网络权威玩法轻量权威实体/Actor相关性和玩法状态决定
高频临时对象带 Generation 的 Actor Pool长时休眠或能力变化后回收
Representation wanted = policy.Resolve(record.capabilities, context);
if (wanted != record.current) {
    Representation next = PrepareRepresentation(record, wanted);
    if (next.IsReady()) CommitSwap(record.id, record.current, next);
}

选择、复制、脚本和存档都只引用 ObjectId;Actor、InstanceHandle、PhysicsHandle 分别带 Generation,旧句柄不能命中新表示。

池化只适合反复生成且初始化昂贵的临时对象。它减少 Spawn/Destroy 尖峰,不减少池中 Actor、Component 和引用的常驻成本;若 Reset 契约不能清空 Timer、委托、网络 Dormancy、物理 Body、异步回调和上一代身份,池化会把性能问题变成状态串台。静态海量对象优先批量表示,临时复杂对象才考虑池化。

六、验证:先证明语义等价,再比较数量

测试必须覆盖 Actor 与实例表示来回切换、选择命中映射、负缩放、材质差异、碰撞升级、复制相关性、撤销删除和迟到异步结果。性能指标包括 UObject/Actor/Component 数、GC 时间、注册尖峰、Draw Call、实例缓冲更新、物化/降级速率和可见空洞帧。

最终决策规则:内容对象永远有稳定身份;只有当前能力需要的对象才拥有 Actor,批量表示的索引永远不能成为业务身份。