20 KiB
spine-unity 4.3 模块化组件升级指南
组件架构重构
📋 本指南的适用范围
本文档仅涵盖 spine-unity 模块化组件迁移流程. 当从 4.2 升级至 4.3 时, spine-csharp 和 spine-unity 中仍包含其他破坏性更改, 在着手模块化组件升级前应先解决这些问题:
- spine-csharp API 变更: 全新引入的姿态(pose)系统显著地改变了访问骨骼、槽位和约束属性的方式
如需获取涵盖 4.2 至 4.3 所有变更的完整迁移步骤, 请参阅以下官方文档:
- 运行时 CHANGELOG.md 的 C# 和 Unity 一节
- 论坛置顶帖 "Spine-Unity 4.2 to 4.3升级指南"
重要提示: 请务必优先完成 spine-csharp API 的迁移, 再依据本指南执行模块化组件迁移操作.
⚠️ 重要提醒: 升级前须知
本提醒仅用于升级现有项目, 新项目可忽略本节内容.
升级后将发生的变化
组件将自动升级并分离为相互独立的动画与渲染组件:
SkeletonAnimation→SkeletonAnimation+SkeletonRenderer组件SkeletonMecanim→SkeletonMecanim+SkeletonRenderer组件SkeletonGraphic→SkeletonAnimation+SkeletonGraphic组件
所有组件设置与字段将被自动迁移 - 不会造成数据丢失.
但请注意: 由于变更了组件类型, 项目脚本中对原组件的引用可能失效 (例如, SkeletonAnimation 不再继承自 SkeletonRenderer).
必须依序执行的项目升级步骤
-
🔒 备份项目 在升级前请完整备份项目. 升级操作将修改场景与预制件文件.
-
📖 通读本指南全文 在执行升级操作前, 务必充分理解全部的破坏性变更点.
-
✏️ 测试并更新你的代码
- 更新代码: 根据本指南修正所有引用了 Spine 组件的脚本, 由于类成员已迁移至模块化类, 项目代码将可能无法编译.
- 测试: 打开若干测试场景, 检查丢了失哪些引用. 未保存的场景仍会保留旧组件数据, 不妨将其作为安全备份——仅当你保存场景后旧组件才会被替换为模块化组件, 此时旧的组件引用便会失效. ⚠️ 警告: 小心对待预制件(Prefab)! 在预制件编辑模式中打开预制件的话, 它会因 Unity 的自动保存机制立即触发组件迁移. 请优先在场景范围内测试, 避免直接操作预制体.
- 可选操作: 也可以一个个地手动重新分配丢失的引用, 或编写一套自动化迁移脚本(详见下文)来自动迁移组件.
⚠️ 重要提示: 自动组件升级仅在 Unity 编辑器打开了场景或预制件时触发. 在构建项目前, 你必须选择 'Upgrade All' 或逐一保存所有场景与预制件来确保没有残留旧组件, 否则可能导致构建中缺失必要组件而失败!
💡 提示: 若控制台输出信息中包含 "SendMessage cannot be called during Awake, CheckConsistency, or OnValidate" 字样,则表明场景中的旧资产已完成自动升级. 此消息将后附日志信息来确认旧组件已成功迁移至模块化组件.
-
🔄 选择升级方式
选项 A - 手动重分配 (推荐小型项目采用):
- 逐一打开各场景与预制件
- 在检查器(Inspector)中手动分配缺失的引用
- 确认无误后保存
选项 B - 自动化迁移 (推荐含大量场景/预制件的大型项目采用):
- 首先编写迁移代码:
- 实现引用迁移模式 (详见下文中的 "防止丢失组件引用" 一节)
- 对于
SkeletonGraphic的引用, 请见 "将已有引用迁至 SkeletonAnimation" 一节
- 在少量文件上测试迁移代码
- 使用
Upgrade All按钮:- 打开
Edit → Preferences → Spine - 在 "Upgrade Scenes & Prefabs" 中
- 点击
Upgrade All按钮
- 打开
若仓促升级可能会导致以下后果
-
场景或预制件中的 Spine 组件引用在保存后将丢失 (引用被置null)
-
在未能升级全部场景/预制件便匆忙执行构建, 可能导致构建过程中缺失必要组件而失败
请勿跳过步骤 1-3, 否则项目极有可能遭到破坏.
📦 可选方案: 4.2 版的两阶段迁移
若你正从 spine-unity 4.2 升级至最新版, 建议遵循两阶段迁移方案来隔离潜在问题:
阶段 1: 升级至 4.3-beta 非模块化组件版本
First upgrade to a 4.3-beta version before the component split changes:
- Commit Hash:
a07b1de - 使用 Git URL 添加包:
https://github.com/EsotericSoftware/spine-runtimes.git?path=spine-csharp/src#a07b1de - 或使用 unitypackage: https://esotericsoftware.com/files/runtimes/unity/spine-unity-4.2-2025-09-26.unitypackage
这一阶段可以:
- 优先解决 4.2 → 4.3 spine-csharp API 变更问题, 同时确保项目正常
- 在升级模块化组件前验证项目稳定性
- 确认项目在 4.3-beta 下稳定后, 有机会再次备份完整项目, 为阶段 2的迁移工作作出充分准备
阶段 2: 升级至最新的 4.3-beta 模块化组件版本
当项目能够在 4.3-beta 非模块化组件版下稳定工作后:
- Up升级至最新 4.3-beta 包
- 按照本指南所述执行模块化组件迁移
- 处理独立的动画与渲染组件
这种两阶段策略可有效隔离问题源头: 项目出现故障时, 可以明确地判断出是 4.2 → 4.3 的 spine-csharp API 变更导致的, 还是模块化组件所致.
📋 简介
spine-unity 4.3 运行时引入了重大架构变更: 相互独立的动画与渲染组件取代原有的继承结构. 该设计让用户可灵活地选用组件, 例如在项目中让 SkeletonMecanim 负责控制动画, 同时采用 SkeletonGraphic 执行渲染——这是此前无法实现的.
关键更改
-
模块化组件: 旧组件被拆分为了相互独立的渲染与动画组件.
-
独立组件架构:
SkeletonAnimation和SkeletonMecanim不再继承自SkeletonRenderer, 而是与独立渲染器组件(ISkeletonRenderer的子类)协同工作, 例如SkeletonRenderer和SkeletonGraphic. -
接口更新: 新增了命名统一的
ISkeletonRenderer和ISkeletonAnimation接口. -
设置分组: 网格生成的相关设置集中到了
MeshSettings属性中. -
自动化迁移: 当启用
AUTO_UPGRADE_TO_43_COMPONENTS(此版本默认启用)后, Unity 编辑器将自动升级组件并迁移已废弃的字段. -
升级全部场景和预制件: 如需一键升级全部场景与预制件, 请打开
Edit - Preferences - Spine, 并在Automatic Component Upgrade中点击Upgrade Scenes & Prefabs-Upgrade All即可.
各组件关系
| 旧架构 | 新架构 |
|---|---|
SkeletonAnimation 继承自 SkeletonRenderer |
SkeletonAnimation + 独立的 SkeletonRenderer 组件 |
SkeletonMecanim 继承自 SkeletonRenderer |
SkeletonMecanim + 独立的 SkeletonRenderer 组件 |
SkeletonGraphic 内置 AnimationState |
SkeletonGraphic + 独立的 SkeletonAnimation 组件 |
适配你的代码
以下为各组件的具体变更说明:
▶️ SkeletonRenderer
破坏性变更
1. 接口变更
- 接口
IHasSkeletonRenderer中的属性名SkeletonRenderer改为Renderer, 类型由SkeletonRenderer改为ISkeletonRenderer.
2. 事件变更
-
SkeletonRendererDelegate类型不再为SkeletonRenderer的嵌套类型.
如需修复编译错误, 只需将SkeletonRenderer.SkeletonRendererDelegate替换为SkeletonRendererDelegate. -
BeforeApply委托类型由SkeletonRendererDelegate更改为SkeletonAnimationDelegate. -
SkeletonRendererDelegate委托签名由SkeletonRendererDelegate(SkeletonRenderer)更改为SkeletonRendererDelegate(ISkeletonRenderer). 该更改会影响以下事件:OnRebuild,OnMeshAndMaterialsUpdated.
如需修复编译错误, 只需将方法实参从SkeletonRenderer更改为ISkeletonRenderer. -
骨骼事件
UpdateLocal,UpdateWorld, 和UpdateComplete从ISkeletonAnimation类 (SkeletonAnimation,SkeletonMecanim) 迁移至ISkeletonRenderer (SkeletonRenderer, SkeletonGraphic)类中. 委托类型由UpdateBonesDelegate改为SkeletonRendererDelegate, 参数由ISkeletonRenderer改为了ISkeletonAnimation.
2. 方法变更
-
LateUpdateMesh()改为了UpdateMesh(). -
移除了
MeshGenerator.TryReplaceMaterials.
3. 执行顺序
SkeletonRenderer和SkeletonGraphic组件接受DefaultExecutionOrder(1)]参数, 以确保其在默认脚本*(即 order=0)*之后执行. 此举保证了即使UpdateTiming置为InLateUpdate, 动画仍能先于 skeleton 更新.
4. 行为变更
- 在启用
singleSubmesh后, 现在也会调用generateMeshOverride.
字段与属性迁移
网格生成器设置
| 旧 API | 新 API | 说明 |
|---|---|---|
skeletonRenderer.zSpacing |
skeletonRenderer.MeshSettings.zSpacing |
已迁移至 MeshSettings |
skeletonRenderer.useClipping |
skeletonRenderer.MeshSettings.useClipping |
已迁移至 MeshSettings |
skeletonRenderer.immutableTriangles |
skeletonRenderer.MeshSettings.immutableTriangles |
已迁移至 MeshSettings |
skeletonRenderer.pmaVertexColors |
skeletonRenderer.MeshSettings.pmaVertexColors |
已迁移至 MeshSettings |
skeletonRenderer.tintBlack |
skeletonRenderer.MeshSettings.tintBlack |
已迁移至 MeshSettings |
skeletonRenderer.addNormals |
skeletonRenderer.MeshSettings.addNormals |
已迁移至 MeshSettings |
skeletonRenderer.calculateTangents |
skeletonRenderer.MeshSettings.calculateTangents |
已迁移至 MeshSettings |
已弃用的小写属性
- 小写属性
initialFlipX,initialFlipY和initialSkinName已被弃用并将于后续版本中移除. 请转用同名大写属性InitialFlipX,InitialFlipY和InitialSkinName.
▶️ SkeletonAnimation
破坏性变更
1. 组件架构
-
SkeletonAnimation 现为独立于 SkeletonRenderer 的组件, 不再继承自 SkeletonRenderer.
-
如需访问渲染器:
skeletonAnimation.Renderer. -
如需通过渲染器访问动画:
skeletonRenderer.Animation.
2. 属性变更
-
state不再是公开属性. 请转用AnimationState属性. -
移除了
valid. 请转用IsValid属性.
3. 方法变更
-
新增
UpdateOncePerFrame()- 仅在该帧未调用Update时执行更新. 已有的Update(float time)保持行为不变. -
不再公开无参
Update()方法, 如需仅在该帧无更新时执行更新, 请使用UpdateOncePerFrame(), 而Update(0)可用于强制执行一次动画更新.
字段与属性迁移
由于 SkeletonAnimation 现已成为独立组件, 曾由 SkeletonRenderer 提供的方法与属性将无法直接通过 SkeletonAnimation 实例访问. 请通过 SkeletonAnimation 实例的 ISkeletonRenderer 访问渲染器属性 skeletonAnimation.Renderer, 而 skeletonRenderer.Animation 属性则可通过 SkeletonRenderer 或 SkeletonGraphic 实例中的 ISkeletonAnimation 访问. 对于未在 ISkeletonRenderer 接口中暴露的成员, 可将 skeletonAnimation.Renderer 显式转换为 SkeletonRenderer 或 SkeletonGraphic 以访问渲染器成员变量.
示例代码
// 升级前: 直接访问 SkeletonRenderer 属性
skeletonAnimation.zSpacing = 0.1f;
skeletonAnimation.AnySkeletonRendererProperty;
// 升级后: 通过 Renderer 对象访问
skeletonAnimation.Renderer.MeshSettings.zSpacing = 0.1f; // 访问 ISkeletonRenderer 接口暴露出的成员
var skeletonRenderer = (SkeletonRenderer)skeletonAnimation.Renderer;
skeletonRenderer.AnySkeletonRendererProperty; // 访问 ISkeletonRenderer 接口未暴露的成员
▶️ SkeletonMecanim
破坏性变更
1. 组件架构
-
SkeletonMecanim 现为独立于 SkeletonRenderer 的组件, 不再继承自 SkeletonRenderer.
-
访问方式同 SkeletonAnimation.
2. 方法变更
-
不再公开
Update(). -
请改用
UpdateIfNecessary(), 如需强制更新请使用Update(0).
字段与属性迁移
与上文中的 SkeletonAnimation 相同
▶️ SkeletonGraphic
破坏性变更
1. 组件架构
-
SkeletonGraphic 不再涉及动画逻辑, 请额外添加 SkeletonAnimation 组件以使用动画.
-
如需访问动画:
skeletonGraphic.Animation.
2. 将已有引用迁至 SkeletonAnimation
若你组件仅通过引用 SkeletonGraphic 来修改其动画属性, 那么建议将引用类型更改为 SkeletonAnimation.
此举便可直接访问动画状态而无需像 ((SkeletonAnimation)skeletonGraphic.Animation).AnimationState 这样进行显式转换, 例如: skeletonAnimation.AnimationState. 请注意, 若希望重命名序列化组件变量, 可在变量声明前添加 [FormerlySerializedAs("previousName")] 特性, Unity 将自动将原字段中保存的序列化值迁移至新变量, 从而保留你在场景或预制件中的已有配置.
示例代码
// Automatically reassign previous serialized values
[FormerlySerializedAs("skeletonGraphic")]
public SkeletonAnimation skeletonAnimation; // Will maintain the reference after upgrade
3. 属性变更
-
已移除属性
AnimationState- 请通过SkeletonAnimation组件查询该属性. -
不再公开
MeshGenerator- 请改用MeshSettings属性和SetMeshSettings()方法. -
MaterialsMultipleCanvasRenderers类型由ExposedList<Material>改为Material[].
4. 创建辅助器(Creation Helper)方法
-
NewSkeletonGraphicGameObject现在默认同时创建SkeletonGraphic和SkeletonAnimation, 以对齐原有行为. 返回类型改为了一个包含了这两个组件引用的结构体. -
已移除
AddSkeletonGraphicComponent, 可用替换为:AddSkeletonGraphicAnimationComponents- 同时创建SkeletonGraphic和SkeletonAnimation组件.AddSkeletonGraphicRenderingComponent- 仅创建SkeletonGraphic组件.
5. 事件更改
- 委托签名从
SkeletonRendererDelegate(SkeletonGraphic)改为SkeletonRendererDelegate(ISkeletonRenderer). 该更改会影响以下事件:OnRebuild,OnMeshAndMaterialsUpdated.
如需修复编译错误, 只需将方法实参从SkeletonGraphic更改为ISkeletonRenderer.
6. 执行顺序
SkeletonRenderer和SkeletonGraphic组件现可接收DefaultExecutionOrder(1)]参数,, 以确保其在默认脚本*(即 order=0)*之后执行. 此举保证了即使UpdateTiming置为InLateUpdate, 动画仍能先于 skeleton 更新.
7. 行为变更 - Material 更新
- 各
CanvasRenderer的 material 不再于每个LateUpdate中更新, 而仅在以下情况时更新:- a) 当 skeleton 更新需更换 materials, 或者
- b) 代码访问了
CustomMaterialOverride或CustomTextureOverride并可能修改它们.
字段与属性迁移
A动画属性
| 旧 API | 新 API | 说明 |
|---|---|---|
skeletonGraphic.AnimationState |
((SkeletonAnimation)skeletonGraphic.Animation).AnimationState |
需显式转换 |
skeletonGraphic.startingAnimation |
skeletonAnimation.AnimationName |
通过 Animation 组件访问 |
skeletonGraphic.startingLoop |
skeletonAnimation.loop |
通过 Animation 组件访问 |
skeletonGraphic.timeScale |
skeletonAnimation.timeScale |
通过 Animation 组件访问 |
skeletonGraphic.unscaledTime |
skeletonAnimation.unscaledTime |
通过 Animation 组件访问 |
网格生成器设置
| 旧 API | 新 API | 说明 |
|---|---|---|
skeletonGraphic.MeshGenerator.settings |
skeletonGraphic.MeshSettings |
直接访问设置 |
⚠️ 其他重要注意事项
防止丢失组件引用
其他组件(例如 SkeletonRenderSeparator)若持有对 SkeletonRenderer 的引用, 且其目标引用曾为 SkeletonAnimation 或 SkeletonMecanim, 则升级后该引用将被置为 null. 这是由于 SkeletonAnimation 与 SkeletonMecanim 不再继承自 SkeletonRenderer, 因而不再构成有效的类型引用. 对此, 手动解决方案是直接不管, 变量类型保持 SkeletonRenderer 不变, 任凭 SkeletonAnimation 的引用被置为 none. 随后再在各场景与预制件中手动分配丢失的引用. 而半自动方案则是: 将项目中 SkeletonRenderer 变量的类型改为 Component (保持对象引用避免丢失目标), 新增一个类型为 SkeletonRenderer(或 SkeletonAnimation)的变量,然后在代码中从 Component 类型变量读取目标对象, 并将其赋给新变量. 例如, 在 Unity 编辑器中给组件添加 [ExecuteAlways] 特性标记, 并在 Awake() 方法中自动执行此操作.
示例代码
// 升级前的类代码
public class TestMigrateReferences : MonoBehaviour {
public SkeletonRenderer skeletonRenderer; // 赋给这个 SkeletonAnimation 的引用将在升级后丢失.
public void Foo () {
skeletonRenderer.skeleton.ScaleX = -1;
}
}
// 升级后的类代码
[ExecuteAlways] // 或者用 [ExecuteInEditMode]
public class TestMigrateReferences : MonoBehaviour {
#if UNITY_EDITOR
[SerializeField, HideInInspector, FormerlySerializedAs("skeletonRenderer")] Component previousSkeletonRenderer; // 如此便能捕获原名为 skeletonRenderer 的 `SkeletonAnimation` 引用.
#endif
public SkeletonRenderer skeletonRenderer;
public void Foo () {
skeletonRenderer.skeleton.ScaleX = -1;
}
#if UNITY_EDITOR
public void Awake () {
AutoUpgradeReferences();
}
public void AutoUpgradeReferences () {
if (previousSkeletonRenderer != null && skeletonRenderer == null) {
skeletonRenderer = previousSkeletonRenderer.GetComponent<SkeletonRenderer>();
if (skeletonRenderer != null)
Debug.Log("Upgraded SkeletonRenderer reference.");
}
}
#endif
}
组件的启用/禁用
由于 ISkeletonRenderer 和 ISkeletonAnimation 组件现已一分为二, 任何控制组件启用/禁用的脚本都必须同时启用/禁用这两个组件.
SkeletonUtilityBone 行为更改
在 Override 模式下, SkeletonUtilityBone 仅在 UpdatePhase.Complete 阶段调整变换(Transform), 不再于 UpdatePhase.World 阶段重复更新, 以减少冗余操作.
自动化迁移
- 当启用了
AUTO_UPGRADE_TO_43_COMPONENTS后, Unity 编辑器将自动迁移废弃字段. - 如需一键升级全部场景与预制件, 请打开
Edit - Preferences - Spine, 并在Automatic Component Upgrade中点击Upgrade Scenes & Prefabs-Upgrade All即可. - 各类中的
UpgradeTo43和TransferDeprecatedFields()方法负责其各自的序列化数据的迁移. - 运行时访问仍需手动更新代码.
常见变更总结
- 添加
.Renderer.前缀便可从动画组件访问渲染属性. - 添加
.MeshSettings.前缀可以访问网格生成设置. - 从 SkeletonGraphic 访问 AnimationState 时, 需 显式类型转换为 SkeletonAnimation.
- 更新委托方法签名: 签名中的具体类型应改为接口类型.
- 使用上述迁移模式升级后要重新绑定丢失的引用.
禁用自动升级检查
当完成了 Spine 资源、场景和预制件的全部迁移工作后, 可禁用自动升级检查来提升编辑器性能:
- 转到
Edit → Preferences → Spine - 在
Automatic Component Upgrade中点击Split Component Upgrade→Disable
此操作将停止 Unity 编辑器在加载场景或预制件时的迁移检测. 如有新资源需要迁移, 可随时重启此功能.
需要帮助?
若在迁移过程中遇到棘手问题, 或发现组件迁移有误, 请前往 Spine 论坛 发帖反馈. 我们将全力协助,确保自动迁移过程尽可能顺畅无痛.