场景内容物 SceneContent
让「关卡里有什么」成为可编辑、可导出、可加载的数据,而不是散落在 prefab 里的隐式引用。与 Config / BT / Attr 平级,不绑定任何具体玩法。
生成物命名空间由「命名空间 root」派生:{root}.scene。
两个来源
- A · 实例条目:在关卡 prefab 上逐个摆的内容物实例(prefab 引用 + 变换 + payload)。
- B · 标记组件:挂在 prefab 子树上的
ISceneContentMarker,由SceneContentAuthoring自动发现。
两者由 SceneContentAuthoring 合并成一个 blob。
核心类
| 类 | 职责 |
|---|---|
SceneContentAuthoring | 挂关卡 prefab 根的 MonoBehaviour,接入 HYC 的「钩子」;A 实例条目与 B 标记组件的聚合容器 |
SceneContentTypeDef | 策划配的「场景内容模板」:一个定义产出标记组件 + 一组可配参数 |
ISceneContentMarker | 标记组件契约;ContentTypeId 是稳定 int |
ISceneContentMarkerPayload | (可选)标记组件自定义 payload JSON 的契约 |
SceneContentRefPath | 关卡内 GO 稳定引用(层级路径);GetPath / Resolve 互逆 |
ISceneContentSpawner | 运行期生成实例的注入点(框架只读 Blob + 解析) |
SceneContentLoader | Load(levelId, spawner, side) 读 Blob 并重组 math 类型交给 spawner |
ISceneContentPrefabResolver | 编辑器接口(SceneContentResolvers.Register 注册),把 prefab 引用解析成 int id 写进 Blob |
运行期加载
// 游戏自己的关卡加载完成后(第三个参数默认 Client)
SceneContentLoader.Load(levelId, mySpawner);
// 专用服务器进程读另一份产物:
SceneContentLoader.Load(levelId, serverSpawner, SceneContentSide.Server);
public class MySpawner : ISceneContentSpawner
{
public void Spawn(int contentTypeId, float3 pos, quaternion rot, float3 scale, NativeArray<byte> payload)
{
// 按 id 解析到 prefab / entity,从 payload(UTF8 JSON)读参数
var json = System.Text.Encoding.UTF8.GetString(payload.ToArray());
// ... 生成 GameObject 或 EntityManager.Instantiate(...) ...
}
}
编辑器入口
HYC Framework/Scene Content/New Scene Content TypeHYC Framework/Scene Content/(priority 70–72,含 Scene Content Window / Export All Blobs / Export Blob (Selected))- 组件挂载:
Add Component → HYC/SceneContent/<类名>
关键约束
⚠
1. blittable:Blob 内只用
2. Blob 落点:
3. 版本:
4. payload 生成方式:都没实现
5. 内容类型 id:类名的 FNV-1a 32 位哈希。改类名 = 换 id,已导出的 blob 必须重导。
int / float(扁平 PosX..RotW..ScaleZ)/ BlobArray<byte>,prefab 引用收成 int id。坐标刻意不用 float3/quaternion(导出器在 Editor 程序集,asmdef 无 Unity.Mathematics 引用,会 CS0012 / EA0003);运行期由 SceneContentLoader 重组。2. Blob 落点:
Assets/StreamingAssets/SceneContent/(服务端加 server/ 子目录),运行期只能从 StreamingAssets 读。3. 版本:
SceneContentBlob.BlobVersion;改条目结构时 +1,运行期 TryRead 版本不符会拒绝。4. payload 生成方式:都没实现
ISceneContentMarkerPayload 时退回 JsonUtility.ToJson(component),此时只能放标量(那个 API 会把 GameObject/Transform 写成 instanceID,跨会话不稳定)。5. 内容类型 id:类名的 FNV-1a 32 位哈希。改类名 = 换 id,已导出的 blob 必须重导。
◈
最小闭环示例(标记组件 + 运行期 spawner + 编辑器解析器)见 示例 · 场景引导 的 Scene Content 小节。注意:解析器类型在框架 Editor 程序集,必须放样例自己的 Editor asmdef。