主题
星火 1.0 → 2.0 迁移参考(reference)
本文件是 migrate-1to2/SKILL.md 的详细版:1.0 工程解剖、如何读 1.0 的 API、三张映射表、分系统迁移配方、手补清单、校验。
> 准确性提醒:1.0 与 2.0 可比拟但有差异。本文标注「需确认」的地方,请用工程内 lua_declare.d.ts、SDK 的 schemas/types/、api/ 实际核对,不要凭印象编造类型名/字段名。
一、1.0 工程解剖
典型 1.0 工程根目录(以一个 ts2lua 模板工程为例):
text
<1.0 项目根>/
├── editor/ # ★ 数据编辑器 + 触发器编辑器的"配置"(source of truth)
│ └── table/
│ ├── entry_data/ # ★ 数据编辑器各类型条目(.ini)
│ │ ├── unit/ buff/ spell/ effect/ actor/ item/ model/ ...
│ │ ├── camera_property/ loot/ link_node/ map_config/
│ │ ├── template@buff/ template@effect/ template@gui_ctrl/ # 模板(继承根)
│ │ ├── const_config.ini # ★ 常量 / 可附加枚举 / 单位属性 / 伤害类型
│ │ └── ui_data.ini # UI 数据
│ ├── package_info.ini
│ └── save_info.json
├── script/ # ★ 服务端:ts2lua 生成的逻辑代码
│ ├── trigger_module_main_*.ts(.lua) # ★ 触发器编辑器生成的逻辑
│ ├── trigger_validator*.ts(.lua) # ★ 数编公式值生成的公式/校验函数
│ ├── lua_declare.d.ts # ★ 1.0 API + 本项目 _OBJ_ 自定义数编类型
│ ├── obj/ # 数编配置生成的数据(lua)
│ ├── scene/ # 场景相关生成代码
│ └── tsconfig.json # typeRoots 指向编辑器 Update 的基础声明
├── ui/
│ ├── script/ # ★ 客户端:结构同 script/(自己的 trigger_module_main / validator / lua_declare)
│ ├── image/ src/ gui/
├── scene/ # ★ 地形/场景资产 + 预放置(见 4.4)
│ ├── .sceneconfig
│ └── <场景名>/ heightdata.dat collision.dat sight.dat map.acmap map.scene_items
│ config.lua area_save.lua unit_save.lua group_nest.json sortinfo.json
├── table/ res/ block/ atmosphere/ lightmap/ game_hud/ i18n/ ref/
├── libs.json # 依赖的脚本库(script_libs)
├── config.ini project.sce要点
editor/= 配置(1.0 是.ini,2.0 是editor/data/*.json)。script/与ui/script/= 配置 + 触发器生成出来的代码。 2.0 没有script/ui\script这两个文件夹——代码全在src/,双端共通,用#if SERVER/#if CLIENT区分单端逻辑。- 服务端 =
script/,客户端 =ui/script/。 两边各有一份trigger_module_main*、trigger_validator*、lua_declare.d.ts。迁移时合并到 2.0 同一份src/代码 +#if。 - 有同名 TS 时优先读 TS。 同时检查独立手写 TS 模块及其初始化/导入链;可只读
main.lua的require查漏。没有 TS 对应的手写 Lua、场景 Lua 表和 UI 配置仍是需要解读的源工件。 script/obj/**、ui/script/obj/**是数编配置生成的 Lua 数据,不直接搬到 2.0;数据迁移以editor/table/entry_data/*.ini或明确选择的代码化路线为基准。INI 可能只保存本地覆盖;默认值、模板继承或服务端/客户端表现配置不明确时,只读对照相应生成 Lua,记录有效值及来源。生成 Lua 也需核对与当前 INI 是否一致,不能把过时产物直接当作权威配置。- 重复构建产物忽略:已确认有 TS 对应的生成
.lua、*.lua.map、*.diagnostic、*_debug_infos.json、tstl.log,不按.lua后缀排除全部文件。 libs.json列出该项目依赖的 1.0 脚本库。这些库在 2.0 多半有对应官方库/能力,但不保证一一对应,属于手补评估项。- 其它配置:1.0 工程根目录
table/下可能还有constant.ini(常量)、mapinfo.ini、floatingtexttemplate.json/riseletter.json(浮动文本/飘字模板)等;game_hud/下可能有小地图(minimap*)等表现资源。按需迁移到 2.0 对应的数据/表现配置(飘字见伤害/表现相关配置;小地图见下「已知不支持」——建议用 Canvas 直接绘制)。
二、如何读 1.0 的 API
1.0 没有 2.0 那样完善的 docs,但有两处声明可"望文生义",都在用户本机:
2.1 工程内的 lua_declare.d.ts(自定义类型)
script/lua_declare.d.ts(服务端)与 ui/script/lua_declare.d.ts(客户端)含:
- 基础枚举(项目用到的常量枚举,如单位属性、Buff 分类等);
- 本项目的自定义数编类型声明,通常以
_OBJ_/_OBJ__开头,例如:
typescript
declare const enum 单位属性 { ["弹道半径"]="弹道半径", ["金币"]="金币", ... }
declare class _OBJ_xxx_yyy extends _OBJ__base_type {
SomeField: number;
...
}> 1.0 的自定义数编类型是单独定义后插入触发器类型;2.0 反过来——数编类型以触发器/代码类型为准。但 lua_declare.d.ts 里这些 _OBJ_* 仍是你了解"这个项目自定义了哪些数编字段"的最佳入口。
2.2 基础官方 API(tsconfig.json → 编辑器 Update 目录)
读工程的 tsconfig.json,其 typeRoots / types 指向用户本机 1.0 编辑器 Update 目录下的基础声明。服务端与客户端路径不同(服务端在 script/,客户端在 ui/script/):
text
服务端: <编辑器 Update 目录>/Res/_m/maps/global_default/<版本>/global_default/script/lua_declare.d.ts
客户端: <编辑器 Update 目录>/Res/_m/maps/global_default/<版本>/global_default/ui/script/lua_declare.d.ts这是 1.0 官方 API 的总声明,类比 2.0 的 API 参考(以及 SDK 根目录 schemas/types/ 的字段 schema),只是没那么完善。查 1.0 的类型/字段时以它为准。
2.3 对照 2.0 的 API
2.0 这边查类型/字段用:schemas/types/GameData*.json(字段 schema)、api/client/ + api/server/(C# 声明 + XML 注释)、docs/systems/*.md(系统说明)。把 1.0 的 _OBJ_ 字段逐个在 2.0 对应 GameData<Type> 里找落点。
区分 C# API 类型形状、数编源 JSON 形状与编辑器元数据;运行时 schema 不一定包含全部作者字段。写入格式以数据编辑器模板/MCP 元数据与实际保存样例核对,再通过生成投影和运行值验证,不能只按 C# 成员名拼 JSON。
三、三张映射表
3.1 目录映射
| 1.0 | 2.0 | 说明 |
|---|---|---|
editor/table/entry_data/<type>/*.ini | editor/data/<Scope>/GameData<Type>/<name>.json | 数据编辑器配置;类型名变(见 3.2) |
script/(服务端)+ ui/script/(客户端) | src/(单源,双端共通) | 单端逻辑用 #if SERVER / #if CLIENT |
script|ui/script/trigger_module_main*.ts | src/ 中的 C# 触发器代码 | 见 4.2 |
script|ui/script/trigger_validator*.ts | 数据字段引用的触发器函数 / C# 委托 | 见 4.3 |
script|ui/script/lua_declare.d.ts | 生成的 src/DataGenerated/ScopeData.cs(强类型 GameLink<T>) | 2.0 由数编 JSON / 代码生成 |
script|ui/script/obj/** | 无(不直接迁) | 1.0 数编生成的 lua 数据 |
tsconfig.json | src/*.csproj | 构建配置 |
scene/<名>/(资产 + lua 预放置) | scene/<名>/(资产可直接复制)+ GameDataScene(场景信息/预放置) | 见 4.4 |
table/mapinfo.ini(旧称 map.info,文件名可能不同,如有) | GameDataGameplay + GameDataScene | 见 3.3 |
3.2 GameData 官方类型名映射
1.0 官方数编类型与 2.0 可比拟,但名称不同(2.0 统一加 GameData 前缀,以区别于真正的运行时对象类型如 Unit/Ability)。字段大致可比拟,但有细节差异。
1.0(entry_data/ 目录名) | 2.0 类型 | 示例命名空间(以 api/、schemas/ 实际为准) |
|---|---|---|
unit | GameDataUnit | GameCore.EntitySystem.Data |
spell | GameDataAbility | GameCore.AbilitySystem.Data |
effect | GameDataEffect*(多子类型:GameDataEffectDamage / GameDataEffectSearch / GameDataEffectUnitModifyUnitProperty …) | GameCore.Execution.Data |
buff | GameDataBuff | GameCore.BuffSystem.Data |
actor | GameDataActor(及 GameDataActorModel 等子类型) | GameCore.ActorSystem.Data |
item | GameDataItem | GameCore.ItemSystem.Data |
model | GameDataModel | — |
unit_level_profile(嵌在 unit 内的子节点) | GameDataUnitLeveling | 见 4.1「嵌套子节点」 |
camera_property | 2.0 镜头相关 GameData | 需确认:在 schemas/types/ 搜镜头类型名 |
loot | 2.0 掉落/奖励相关(如 GameDataReward*) | 需确认 |
link_node | GameDataControl*(UI 控件) | GameUI 体系,见 4.7 |
map_config / table/map.info | GameDataGameplay + GameDataScene | 见 3.3 |
const_config(常量) | 可扩展枚举 + GameDataUnitProperty + GameDataDamageType | 见 3.3、4.5 |
template@* | 2.0 数编继承($inherit / 根节点继承) | 见 4.1 |
注意字段级差异:例如 1.0 把技能动画直接填在技能表里,2.0 的技能动画可指向单独的 GameDataAnimation 节点(见 4.6)。逐字段务必对照 2.0 schema/api 落点,别假设字段名一致。
3.3 概念映射(重设计的机制)
| 1.0 概念 | 2.0 落点 | 关键差异 |
|---|---|---|
| 可附加枚举(const_config 里配置) | 可扩展枚举(EnumExtension),扩展到整个枚举类型级别 | 在代码或触发器里扩展;扩展枚举名以 E 开头、生成时去掉 E 前缀。见 EnumExtension、02-高级功能 |
| 可附加枚举里的单位属性 | 独立数据类型 GameDataUnitProperty | 过去 Gameplay 表里"针对单位属性的可附加枚举公式系统",现内化为 GameDataUnitProperty 自身的属性字段。见 UnitPropertySystem |
| 伤害类型 | GameDataDamageType | 从可扩展枚举变成独立数据类型,公式在自己表里定义,不再全塞进 gameplay 表 |
table/map.info | GameDataGameplay + GameDataScene | 关键值内化;部分原全局配置改为按场景区分(如寻路模式、视野模式等) |
| 数编公式值 = 内嵌触发器 json 到 ini | 数据字段直接引用触发器函数 / C# 委托 | 1.0 繁琐冗长;2.0 简洁,见 4.3 |
| 客户端/服务端两个文件夹 | 同一份 src/ + #if CLIENT/#if SERVER | 提倡双端共通代码 |
四、分系统迁移配方
> 决策树:先沿用用户确认的作者路线。允许普通 C# 时,逻辑/触发器/公式优先代码化;明确要求可视化维护时,用 trigger-editor-mcp 保留可编辑结构。数据需数编维护时用 data-editor;允许纯代码定义时可按复杂度权衡。token 成本不能替代可维护性和保真度要求。
4.1 数据编辑器
1.0 长这样:editor/table/entry_data/unit/<名>/entry_data.ini,Lua 表语法,NodeType='$$.unit.Unit',字段含中文键、可能内嵌 IsFunc/LuaCode/Func 公式串。
2.0 怎么写:
- 路径 →
editor/data/<Scope>/GameData<Type>/<名>.json,$type指向 2.0 类型(如GameCore.EntitySystem.Data.GameDataUnit),引用其它数编用$<Link>.Root形式。用 data-editor 处理$id/$inherit/ link 路径与保存边界。 - 自定义类型且继续使用图形化编辑器:在触发编辑器 Class 的属性面板选择“设置为数编分类/类型”,保存并生成代码后,再回数据编辑器创建条目。
- 或明确选择纯代码化:用
[GameDataNodeType<T,V>]+partial class定义类型、用new GameData...(link){ ... }写条目(见 GameData 系统)。 - 1.0 的
template@*→ 2.0 用数编继承($inherit或以某根类型为父)表达。
坑:类型名变(3.2);字段不一一对应,逐字段对 schema/api 找落点;技能动画拆到 GameDataAnimation(4.6)。
首次写入一种节点前,用目标编辑器的 gamedata_list_types / gamedata_get_type_schema 确认完整 $type、是否可实例化及引用目标类型;无对应 MCP 时查目标 SDK schema/API 和实际保存样例。保存后全量生成,检查结构化诊断与实际赋值,按 quality-gates.md 4.4 处理 GDATA001。能通过 C# 编译不代表字段没有在生成时被省略。
嵌套子节点:1.0 的 ini 条目常含嵌套子节点(如 unit 内的 Unit_Level_Profile、技能内的多个效果节点),每个子节点都有自己的 NodeType。逐个把 NodeType 值在 2.0 schemas/types/ 里找对应 GameData*(例如 $$.unit_level_profile.* → GameDataUnitLeveling、$$.effect.* → GameDataEffect*),别只迁顶层节点。
技能/普攻:2.0 主动技能用 Time.NormalizedDuration 字段(主动技能基类 GameDataAbilityActive 上,见 GameDataAbilityExecute 等)直接控制最小攻击间隔/普攻节奏,不必像 1.0 那样写复杂公式同时操作四阶段时间与冷却。见 AbilitySystem 与 3d-unit-game 的普攻配置。
4.2 触发器
1.0 长这样:script/trigger_module_main_*.ts 里用 base.trigger_new(callback, ...) 注册;事件转发、初始化逻辑等。客户端版在 ui/script/。
2.0 怎么写:
csharp
// 一行式订阅(推荐)
var t = Game.Subscribe<EventEntityDeath>(async (sender, e) =>
{
Game.Logger.LogInformation("单位 {Name} 死亡", e.Entity.Name);
});
// 或标准式
var trigger = new Trigger<MyEvent>(OnMyEvent);
trigger.Register(Game.Instance); // 也可 Register(unit) / Register(unitData)- 事件可注册到
Game.Instance(全局)/ 实体 / 数编表对象(数据类型级)。 - 客户端专属逻辑包
#if CLIENT,服务端专属包#if SERVER。 - 框架约定:用
Game.Delay()不用Task.Delay();不要用Task.Run(),也不要使用TaskCreationOptions.RunContinuationsAsynchronously;日志用Game.Logger(结构化),不用Console.WriteLine、不用字符串内插。 - 详见 TriggerSystem、01-核心差异;用 MCP 操作触发器见 trigger-editor-mcp。
4.3 公式值与 Validator
1.0 长这样:数编 ini 里公式值是内嵌的触发器 json;生成到 script\|ui/script/trigger_validator*.ts,形如 export let validator_xxx = (...) => { ... }。
2.0 怎么写:数据字段直接是触发器函数 / C# 委托:
csharp
new GameDataBuff(buffLink)
{
Modifications = [
new () {
Property = ScopeData.UnitProperty.LifeMax,
Value = (context) => context.Target.GetUnitPropertyFinal(ScopeData.UnitProperty.Strength) * 2,
}
],
};#if放置规则必须遵守 GameDataFormulaPlacement:字段只在一端 API 存在就只在对应#if赋值;FunctionBias.Server默认放#if SERVER;GameDataEffectXXX的效果公式默认按服务端处理;常量/双端共有 API 的公式可双端共享。- 公式参数是
IExecutionContext(可取施法者/目标)或具体上下文(如响应节点的ResponseContextDamage),不再是 1.0 的效果节点参数。见 02-高级功能·通用公式。 - 1.0 技能公式历史遗留:1.0 技能节点里一些本该支持公式的字段只能填数值,要勾选"使用数值公式"再到单独的"数值公式"字段填公式。2.0 的技能/物品/Buff 在脚本层完全重新实现,公式与数值不再分开——只有一个公式字段。迁移时把 1.0 的"数值 + 数值公式"两处合并成 2.0 的单一公式字段即可。
4.4 场景与地形
基础地形/场景资产文件 1.0 与 2.0 同格式,可直接复制使用。1.0 工程不包含 Volumetric3D 场景,因此默认迁移不需要生成 2.0 的 3D 场景产物;只有目标工程主动改用 Volumetric3D 时,才按 3DSceneSetup 重新生成派生产物。主要差异与处理方式:
| 资产 | 1.0 文件名 | 2.0 文件名 | 实测 |
|---|---|---|---|
| 高度图 | heightdata.dat | HeightData.dat | 同格式(头部一致,zlib 压缩),仅大小写改了 |
| 寻路碰撞 | collision.dat / clientcollision.dat / editorcollision.dat | Collision.dat / ClientCollision.dat / EditorCollision.dat | 同格式,仅大小写 |
| 视野 | sight.dat / editorsight.dat | Sight.dat / EditorSight.dat | 同格式 |
| 地块 | map.acmap | map.acmap | 同格式 |
| 地形信息 | map.scene_items | map.scene_items | 头部逐字节相同(JSON 文本) |
| 场景配置 | config.lua | config.lua | 同结构;内部链接从 $$.xxx.root 变为新 GameLink id($01K...) |
| 区域/预放置 | area_save.lua / unit_save.lua | 同名同在 | 同格式 |
只有几处真实差异(都不是"地形格式变了"):
- 目标工程可能有
scene_info.xml、PhysicsCollision.dat等 2.0 派生产物;1.0→2.0 默认迁移不需要生成PhysicsCollision.dat,只有目标场景主动升级为Volumetric3D时才按 2.0 编辑器流程生成。 - 场景信息 + 预放置物体额外要写进
GameDataScene(1.0 用scene/<名>/area_save.lua、unit_save.lua的 Lua 表记录)。
迁移配方:
- 把 1.0
scene/<名>/的资产文件复制到 2.0 工程对应场景文件夹。 - 用 2.0 编辑器打开项目,确认目标
GameDataScene、场景入口、尺寸和相机等链接;默认 1.0→2.0 迁移不要求生成PhysicsCollision.dat。如果用户明确把目标场景升级为Volumetric3D,再按 3DSceneSetup 生成 3D 场景产物。 - 把
area_save.lua/unit_save.lua里的点/线/区域/预放置单位,誊写进GameDataScene的预放置字段(PlacedSceneShapes/PlacedPlayerObjects等,字段名以 GameDataScene schema 为准)。部分原全局配置(寻路/视野模式)现按场景配在GameDataScene,见 SceneSystem、SceneVisionSystem。 - 在编辑器场景列表中核对所有预期入口,并保存、重开复查。编辑器元数据如
Path可能不在运行时 schema 中,不能仅因 schema 未列出就删除;先对照编辑器创建的有效场景源文件及 MCP 元数据。矩形区域的两角坐标不能直接当作中心/尺寸,见 4.9。 - 覆盖目标模板的同名场景后,检查
editor/terrain/scenes/<名>/的 authoring projection 及关联派生产物是否仍属于模板旧地形。通过目标编辑器实际提供的场景状态、保存和资源生成工具刷新并回读;source_stale、保存检查点未到达或投影无效都不能计作保存成功,也不能把旧投影导入刚复制的地形。仅当确认是本次骨架产生、且无用户编辑的模板残留时,才可留档移出;用户已有投影需保留并单独处理。尚未生成投影时如实记录,不能伪造 manifest/hash 或额外启用不需要的 3D 烘焙来消除提示。
4.5 单位属性 / 可扩展枚举 / 伤害类型
- 可附加枚举 → 可扩展枚举:用
[EnumExtension(Extends = typeof(...))]扩展已有枚举,或[EnumExtension(Extendable = true)]定义新可扩展枚举。枚举名必须以E开头(生成时去掉E),且只能用于直属命名空间的枚举。例:csharp[EnumExtension(Extends = typeof(PropertyUnit))] internal enum EGameplayPropertyUnit { MagicPower, CriticalRate, Inventory } // 使用:unit.SetProperty(GameplayPropertyUnit.MagicPower, 100.0); - 单位属性 →
GameDataUnitProperty:1.0 在 const_config / Gameplay 表里配的单位属性公式,现内化为GameDataUnitProperty自身字段。见 UnitPropertySystem。 - 伤害类型 →
GameDataDamageType:公式在自己表里定义。 - 详见 EnumExtension 与 02-高级功能。
4.6 动画
- 1.0 技能表里直接填的动画 → 2.0 可指向独立
GameDataAnimation节点(GameDataAnimationSimple/GameDataAnimationSequence/GameDataAnimationBracket)。见 ModelAnimationSystem、schemas/types/GameDataAnimation*.json。 - 核对完整类型与引用链:当前简单动画节点为
GameCore.ModelAnimation.Data.GameDataAnimationSimple;不要因GameDataAnimation基类位于资源类型命名空间就推测其子类型也在同处。仍以目标版本查询为准。核对Ability.Animation→ 可实例化动画节点 → 模型真实片段名及大小写,生成后确认赋值存在,并实际播放;资源路径存在或技能命令成功不能代替动画验收。 - 捏人/共享人形动画:资源统计会尝试沿
GameDataUnit.Model/Abilities→GameDataAbility.Animation→GameDataAnimation素材自动收集烘焙关系,但这是依赖代码结构的静态分析,不保证覆盖 helper、工厂或运行时动态组装。关键动画可继续在对应GameDataModel.HumanoidSourceAnimations中显式填写(≈ 1.0 数据编辑器的“额外加载动画”)作为保险。之后仍需在编辑器手动执行动画重定向(工具 → 资源统计和动画重定向 → 统计资源并生成)。也可手动维护ref/model_animation.json后只执行菜单中的“生成”;再次统计资源会覆盖手工 JSON。见 04-限制。
4.7 UI
2.0 UI 编辑器 / UI Authoring 已进入工具链,但仍处于早期阶段,覆盖范围与 1.0 不等价;同时支持以下构造法(见 03-UI系统):
- 数编模板:
GameDataControl*定义模板 →Control.Xxx.CreateButton()实例化。与 1.0「存配置生成代码」的路径最像,适合静态/复杂/可复用 UI。 - 运行时动态:
new Button{ ... }、设Parent、订阅OnPointerClicked、AddToVisualTree()。 - 流式语法:
Button().Size(...).Center().Background(...),见 FluentUILayoutGuide、ui-layout-api。
迁移 1.0 UI(控件在 ui/script + link_node;事件响应触发器配置在 ui/src/gui/ui_response/——触发器 json 配置,后缀虽是 .lua——生成代码在 ui/script/gui/ui_response/。UI 事件必在客户端,故都在 ui/ 下;仅当项目有自定义 UI 事件响应时存在):
- AI 助手按场景选择 UI Authoring、流式(Flex)、运行时代码或数据驱动模板;流式语法仍适合快速构造,但复杂交互和最终行为必须走普通客户端运行时验证。见 ui-authoring-mcp、ui-layout-api、FluentUILayoutGuide。也可直接代码对代码翻译。
- 挂载差异(易漏):1.0 控件创建时默认挂上 visual tree;2.0 需主动挂(
AddToVisualTree()或流式的AddToRoot()),漏挂则控件不显示。迁移完整页面或菜单时,优先把页面根节点写成UI.Page(),再把实际内容容器FillParent()到Page内部。 - 控件类型也是数编类型:1.0 控件类型在
lua_declare.d.ts里同样以_OBJ__开头(设计上是数编类型的一种),对应 2.0GameDataControl*。 - UI 代码通常包
#if CLIENT。2D 绘制见 canvas-2d-game、CanvasDrawingSystem。"物品额外属性"在 2.0 改名为"物品动态属性",客户端可读(1.0 客户端读不到公式属性的痛点已解决)。
4.8 表现资源与客户端注册
模型、动画和 Actor 的迁移应把“资源入口”和“依赖闭包”分开检查。prefab 或模型路径存在时,仍需确认其 mesh/mdl、材质、纹理、动画、碰撞、Socket 及粒子 Actor 依赖可被目标客户端解析;不要把文件存在视为运行时可用。
资源目录迁移
- 将 1.0 工程根目录的
res/按相对路径整体合并到 2.0 项目res/。这一步不能省略:旧项目的地形、模型、材质、粒子、音频或场景配置可能通过res/...间接依赖,即使当前.ts/.ini没有直接出现完整路径。 - 将
ui/image/、ui/spine/及其配套的.atlas、.skel、.json、贴图等文件一起复制;若源工程使用ui/Spine/,保留源目录大小写并按 ResourcePathGuide 转换代码路径。不要复制生成产物或目标项目已有的ui/AppBundle/、AppBundle/managed/。 - 合并时记录同名文件冲突并以目标工程实际引用为准;不要用空壳资源、伪造模型或伪造动画文件掩盖缺失依赖。
- 复制后执行一次
Client-Resource,检查ref/objref.txt是否包含关键资源;发布到不同运行环境时,还要确认自定义云端资源在目标环境存在。
运行时创建的单位,其客户端可见部分应与服务端创建逻辑分离:
GameLink、基础GameDataUnit、Model、状态栏和客户端需要解析的 Actor/Ability 数据放在双端共享区域;- 动态属性公式、AI、创建/销毁、死亡和权威战斗逻辑按 API 能力放入
#if SERVER; - 服务端和客户端分别编译后,仍需用客户端日志或截图确认单位可见。
1.0 技能动画名可能只是逻辑别名,迁移时应在目标模型中核对真实片段名和大小写,再通过 GameDataAnimation 指定。特殊技能的预警、投射物、爆炸和伤害应尽量共享同一落点/载体作用域;若 Actor 挂在载体上,搜索或命中后应留出清理延迟,避免表现随载体立即消失。
1.0 数据复用边界:
- 直接复用源配置中的坐标、数量、半径、时间、伤害公式和已确认完整的资源路径;
- 不假设 1.0 的 Effect/Actor 运行时结构可被 2.0 原样加载;
- 用 2.0 的
TargetLocation、执行上下文、Mover、Model Event、Socket 和 Actor 生命周期重新表达节点关系; - 每个阶段明确位置所有者,避免技能原始目标、随机点、新载体和默认目标混用。
迁移垂直下落表现时,先检查运动是否已编码在模型动画、Model Event 或 Socket 中。若起点和落点的水平坐标相同,不要默认使用依赖水平朝向的投射物移动器,也不要通过增加水平偏移制造方向;优先采用地面载体统一预警、落点、爆炸和伤害中心,再由模型动画或 Socket 提供高度变化。
4.9 高风险语义与字段回读
遇到以下映射时,在批量转换前选一个非默认样例核对。表中给出检查点,具体字段、默认值与序列化格式仍以目标 SDK/编辑器版本为准;版本缺陷应记录最小复现,不写成永久能力限制。完整四层回读流程见 quality-gates.md 4.4。
| 映射场景 | 必须辨认的语义 | 最小验证 |
|---|---|---|
| 两角矩形 → 区域配置 | 目标字段若要求左上角 + 尺寸,先按其坐标约定求角点与宽高;不要当中心点,也不要额外旋转整张地图坐标 | 用非原点、非正方形区域核对两个角与边界进出 |
| Cast / Channel → 技能阶段 | 对照源事件触发时机、首次效果、周期和结束;名称近似不代表阶段相同 | 例如立即首击、每 0.5 秒、共 8 次,记录实际时间轴 |
| 响应上下文与关系筛选 | 分辨 Caster、Default 及响应事件提供的目标;Player 与 Alliance 关系不可凭字面互换 | 同时测试自己、同玩家另一单位、盟友、敌人及无效目标 |
| 模板集合与实例继承 | 先看模板有效值和集合合并方式;不能假设子集合覆盖父集合,也不能把实例当模板注册 | 核对最终背包、筛选器、效果列表和默认行为,无额外样例项 |
| 值对象 / 集合 getter | getter 可能返回副本;配置写对、生成器调用 AddRange 并不证明实例已更新 | Footprint 等集合核对保存源、生成赋值和运行数量;缺少 setter 回写时按缺陷定位 |
| 物品计数与容器操作 | 不可堆叠物品的计数字段含义、载体初始化、同载体交换与跨载体放入、部分堆叠需分别核对;查目标 Swap / Put 等 API 契约 | 单件、多件、满格、部分合并、跨仓库移动后总量守恒,失败无丢失/复制 |
| C# 包装类型 → JSON | 如 WeightedLinkComplex 在 C# 可有包装 API,不能据此编造 JSON 对象结构;先核对 schema/已保存样例的数组形状 | 保存并重新读取一项非空效果列表,再运行确认效果实际触发 |
| 任务等非默认字段 | 按实际 schema/API 选择字段,如 TargetCount,不要猜测 RequiredCount 一类近义名称 | 设置为 3,重新读取并运行确认 1/3 → 2/3 → 3/3 |
涉及触发器导入/替换时,再核对生成的表达式优先级、变量初始化位置、嵌套引用和函数入口,而非仅检查工具返回成功。若最小样例已暴露工具或生成器问题,保留输入、保存后输出、版本和诊断,将受影响功能标为待修复;替代路线需符合用户已选作者方式,并记录差异。
五、手补清单与已知不支持
迁移收尾,逐条核对并如实告知用户:
- [ ] 坐标系:2.0 默认镜头转了 90°(仅为统一 2D/3D 坐标规律,非强制,可配回 1.0 朝向)。别换算坐标数据——地形与场景/预放置坐标整体复制、彼此一致,换算反而要连地形一起转。只复查代码里硬编码的方向假设("屏幕上方=某轴"、UI↔场景手动换算)。见 COORDINATE_SYSTEM_GUIDE。
- [ ] 类型/字段差异:3.2 标「需确认」的类型名(camera/loot 等)务必对
schemas/types/核实;逐字段对落点。 - [ ] 公式
#if放置:按 GameDataFormulaPlacement 检查,避免客户端编译失败。 - [ ] 场景预放置:
area_save.lua/unit_save.lua的区域与预放置物体已写入GameDataScene? - [ ] 捏人动画重定向:
ref/model_animation.json是否包含目标模型与动画,编辑器里是否已生成重定向?关键动画是否需要用HumanoidSourceAnimations显式兜底? - [ ] 依赖库:
libs.json里的 1.0 script_libs 是否都有 2.0 对应能力?无对应的需手工实现。 - [ ] 小地图:检查
game_hud/minimap*是否存在;2.0 没有与 1.0 等价的完整内置小地图工作流,但可使用MiniMapIcon或 Canvas 自行补表现,见 canvas-2d-game、CanvasDrawingSystem。 - [ ] 编译 + 运行:
Server-Debug与Client-Debug都过;实际跑起来核对行为(wasicore-dev、GameCompletenessChecklist)。
2.0 暂不支持 / 缺失(04-限制):
- 场景拼接功能:暂未加入(这类 1.0 项目极少,今后会加)。
- 小地图:没有与 1.0 等价的完整内置工作流;可用
MiniMapIcon或 Canvas 自行实现所需表现(见 canvas-2d-game)。 - 部分小卡片机制:可能未覆盖(商城已支持);未覆盖的先用代码/API 实现。
六、校验
- 编译:用 2.0 编辑器调试按钮,或
dotnet build src/GameEntry.csproj -c Server-Debug与-c Client-Debug。有错先修再继续。 - 运行:在编辑器调试,或用 client-only-debug 启动纯客户端核对 UI。
- 行为核对:对照原 1.0 项目,抽查关键单位/技能/Buff/场景预放置/UI 是否一致;动态行为异常用 behavior-troubleshoot 排查。
- 逐块推进:每迁完一个子系统就编译+跑一次,不要堆到最后一起验。