Skip to content

Entity 与 Actor 的分工 ​

本文针对 SCE Unit/技能体系。需要选整个游戏的实现路线时,先看游戏架构路线:GameGraph 场景图和 Canvas 也可以承担游戏功能。

各自提供什么 ​

对象用途创建与同步边界
Entity / Unit单位位置、属性、技能、战斗等运行时状态游戏单位由服务端创建,框架按同步和可见性规则向客户端复制
Actor模型、粒子、音效、光束、文字等表现实际表现由客户端创建和渲染;通过 ActorScope 管理生命周期与可见性
ActorScopePersist管理依附实体等宿主的持久表现服务端创建并同步 Scope,客户端据此创建表现
ActorScopeTransient一次性表现客户端播放;服务端可请求可见客户端播放

“持久 Scope”描述的是局内生命周期,不代表保存到 CloudData。同步到客户端的属性范围、可见性和频率也不能概括成“所有状态自动同步”。

常用接线 ​

  • 单位主体模型、武器或状态表现:先检查单位、技能、Buff 等定义中的 Model、ActorArray 与 Scope 配置,复用框架的创建与销毁流程。
  • 客户端本地预览:在客户端使用 Actor 或 GameGraph,并管理退出预览时的清理。
  • 服务端触发一次爆炸、提示音等表现:通过瞬态 Scope 的播放流程请求客户端显示,见 Actor 系统。
  • 服务端管理固定场景标记或单位持续光环:通过持久 Scope 的 SetActorSlot(...) 声明,见服务端创建表现。
  • 直接 GameGraph 的多人对象:使用服务端创建的复制场景图/节点并 Publish(player),见架构路线。

这些选择取决于需要的能力。单纯“有逻辑”或“需要同步”不足以推导出必须使用 Entity;Actor 也可以有客户端表现逻辑,但不因此获得服务端权威的伤害、货币或存档状态。

容易写错的地方 ​

在服务端直接构造 Actor ​

csharp
#if SERVER
// 错误:ActorModel 的服务端构造路径没有实现实际 Actor 创建。
var actor = new ActorModel(actorLink, false, scope);
#endif

部分 Actor 类型在服务端声明中仍可见,但 Actor 的服务端构造实现会抛出 NotImplementedException。通过编译不能证明这条路径可用。

应根据用途配置宿主的 ActorArray,或通过 Scope 的 PlayTransient(...) / SetActorSlot(...) 发起表现,见服务端创建表现。客户端本地直接创建的形式是:

csharp
#if CLIENT
// actorLink 为已有 Actor 定义,scope 为本次表现的有效 Scope。
Actor? actor = actorLink.Data?.CreateActor(scope);
#endif

把显示状态当成权威状态 ​

隐藏或销毁 Actor 不等同于击杀单位;移动表现也不等同于改变服务端单位位置。战斗和状态变化通过单位/效果等对应系统执行,表现随结果更新。

反过来,单位和 Entity 也提供动画桥接能力,不能把“所有动画调用都必须写在 Actor 类里”当成框架要求。见 GameCore 与 GameGraph 桥接。

重复创建或未清理表现 ​

框架已通过 Model / ActorArray 创建表现时,再手工创建一套可能产生重叠模型、重复音效。附着效果先检查 Scope、挂点和跟随配置;表现退出时检查宿主级联销毁与瞬态播放结束流程。

没有附着到正确 Scope 的表现,不能仅凭位置与单位相同就认为它会随单位销毁。详细生命周期与播放方式见 Actor 系统。

相关文档 ​