spine-runtimes/spine-unity/Assets/Spine/Documentation/4.3-split-component-upgrade-guide.md

374 lines
22 KiB
Markdown

# spine-unity 4.3 Split Component Upgrade Guide
## Component Architecture Restructuring
> **Note:** You can find Chinese and Japanese translations of this upgrade guide right next to this file.
> * [中文版 4.3 分体组件升级指南 - Chinese 4.3 Split Component Upgrade Guide](https://github.com/EsotericSoftware/spine-runtimes/tree/4.3-beta/spine-unity/Assets/Spine/Documentation/4.3-split-component-upgrade-guide-zh.md)
> * [日本語版 4.3 分割コンポーネントアップグレードガイド - Japanese 4.3 Split Component Upgrade Guide](https://github.com/EsotericSoftware/spine-runtimes/tree/4.3-beta/spine-unity/Assets/Spine/Documentation/4.3-split-component-upgrade-guide-ja.md)
---
## 📋 Scope of This Document
**This document covers only the spine-unity component split migration.** From version 4.2 to 4.3, there have been additional breaking changes in both spine-csharp and spine-unity that you need to address before handling the component split:
- **spine-csharp API changes:** New pose system affecting bone, slot, and constraint properties
For complete migration steps covering all 4.2 to 4.3 changes, please refer to:
- The [CHANGELOG.md](https://github.com/EsotericSoftware/spine-runtimes/blob/4.3-beta/CHANGELOG.md#c-2) document (sections C# and Unity)
- The forum post ["Spine-Unity 4.2 to 4.3 Upgrade Guide"](https://esotericsoftware.com/forum) for a comprehensive migration guide
**Important:** Complete the spine-csharp API migration first, then proceed with the component split migration described in this document.
---
## ⚠️ IMPORTANT: Before You Upgrade
**This warning only applies to existing projects being upgraded. New projects can safely ignore this section.**
### What Will Happen
Components will be **automatically upgraded** and split into separate animation and rendering components:
- `SkeletonAnimation``SkeletonAnimation` + `SkeletonRenderer` components
- `SkeletonMecanim``SkeletonMecanim` + `SkeletonRenderer` components
- `SkeletonGraphic``SkeletonAnimation` + `SkeletonGraphic` components
All component settings and fields will be automatically transferred - nothing will be lost.
**However:** Due to these type changes, existing references in your custom scripts may be lost because the component types no longer match (e.g., `SkeletonAnimation` is no longer a subclass of `SkeletonRenderer`).
### Required Upgrade Steps (In Order):
1. **🔒 BACKUP YOUR PROJECT**
Create a complete backup before upgrading. These changes will modify your scenes and prefabs.
2. **📖 READ THIS ENTIRE DOCUMENT**
Understand all breaking changes before proceeding.
3. **✏️ TEST AND UPDATE YOUR CODE**
- **Update your scripts:** Fix custom scripts that reference Spine components according to this document, as your code may no longer compile when members were moved to the split classes
- **Test:** Open a few test scenes to see which component references are lost. Unsaved scenes still contain the old component data and serve as a safety backup - only when you save will the split components replace the old ones and references be lost.
**⚠️ WARNING:** Prefabs behave differently! Opening a prefab in Prefab Edit Mode will automatically save the component migration due to Unity's prefab auto-save feature. Always test with scenes first, not prefabs.
- **Decide:** Either manually re-assign lost references, or write migration code (explained below) to handle this automatically
**⚠️ IMPORTANT:** Automatic component splitting only happens when scenes/prefabs are opened in the Unity Editor. You must choose 'Upgrade All' or save each scene/prefab before building your game, otherwise the old single components won't be split and half the required components might be missing in the build!
**💡 HINT:** If you encounter the Console log output "SendMessage cannot be called during Awake, CheckConsistency, or OnValidate", this is a sign that old un-migrated assets were present in the scene which were just auto-upgraded. These messages will be followed by a log message confirming that an old component was auto-migrated to split components.
4. **🔄 CHOOSE YOUR UPGRADE PATH**
**Option A - Manual re-assignment (recommended for small projects):**
- Open each scene and prefab individually
- Manually re-assign lost references in the Inspector
- Save when satisfied
**Option B - Automatic migration (for large projects with many scenes/prefabs):**
- Write migration code first:
- Implement the reference migration pattern (see "Preventing Lost Component References" section below)
- For `SkeletonGraphic` references, see "Changing Existing References to SkeletonAnimation" section
- Test migration code on a few files
- Then use `Upgrade All`:
- Go to `Edit → Preferences → Spine`
- Under "Upgrade Scenes & Prefabs"
- Click `Upgrade All` button
### What Will Break If You Don't Prepare:
- Component references in scenes or prefabs may be lost (set to null) once you save your scenes or prefabs
- Building before upgrading all scenes/prefabs may result in missing components in the build
**Do not proceed without completing steps 1-3, or you risk breaking your project.**
---
## 📦 Optional Two-Step Migration from 4.2
If you're migrating from spine-unity 4.2, you may find it easier to upgrade in two steps to isolate potential issues:
### Step 1: Upgrade to a 4.3-beta pre-split version
First upgrade to a 4.3-beta version before the component split changes:
- **Commit Hash**: `a07b1de`
- **add package via Git URL**: `https://github.com/EsotericSoftware/spine-runtimes.git?path=spine-csharp/src#a07b1de`
- or **unitypackage**: https://esotericsoftware.com/files/runtimes/unity/spine-unity-4.2-2025-09-26.unitypackage
This intermediate step allows you to:
- Fix any issues related to the 4.2 → 4.3 spine-csharp API changes first and ensures your project works
- Verify your project is stable before proceeding
- Once your project is working with this 4.3-beta version, create another backup before proceeding to step 2
### Step 2: Upgrade to latest 4.3-beta version (with split components)
Once your project is working with 4.3-beta:
- Upgrade to the latest 4.3-beta package
- Follow the component split migration guide above
- Handle the separated animation and rendering components
This two-step approach helps isolate issues - if something breaks, you'll know whether it's due to the 4.2 → 4.3 spine-csharp changes or the component split specifically.
---
## 📋 Introduction
The spine-unity 4.3 runtime introduces a major architectural change: **separation of animation from rendering by using two separate components instead of component inheritance**. This enables flexible combinations like using `SkeletonMecanim` for animation with `SkeletonGraphic` for rendering, which was previously not possible.
### Key Changes:
- **Component Split**: The previously monolithic components have been split into separate rendering and animation components.
- **Separate Components**: `SkeletonAnimation` and `SkeletonMecanim` no longer inherit from `SkeletonRenderer`. They now work alongside a separate renderer component (a subclass of `ISkeletonRenderer`), such as `SkeletonRenderer` and `SkeletonGraphic`.
- **Interface Updates**: New `ISkeletonRenderer` and `ISkeletonAnimation` interfaces with updated property names.
- **Settings Grouping**: Mesh generation settings are now grouped under `MeshSettings` property.
- **Automatic Migration**: The Unity Editor will automatically upgrade your components to the new split components and transfer deprecated fields when `AUTO_UPGRADE_TO_43_COMPONENTS` is defined (*the default*).
- **Upgrade all Scenes and Prefabs**: To upgrade all scenes and prefabs at once, go to `Edit - Preferences - Spine` and under `Automatic Component Upgrade` hit `Upgrade Scenes & Prefabs` - `Upgrade All`.
### Component Relationships:
| **Old Architecture** | **New Architecture** |
|---------------------|---------------------|
| `SkeletonAnimation` inherits from `SkeletonRenderer` | `SkeletonAnimation` + separate `SkeletonRenderer` component |
| `SkeletonMecanim` inherits from `SkeletonRenderer` | `SkeletonMecanim` + separate `SkeletonRenderer` component |
| `SkeletonGraphic` provides embedded AnimationState | `SkeletonGraphic` + separate `SkeletonAnimation` component |
---
## Adapting Your Code
Here's what changes for each component:
## ▶️ SkeletonRenderer
### Breaking Changes
#### 1. Interface Changes
- `IHasSkeletonRenderer` interface changed property name from `SkeletonRenderer` to `Renderer`, type from `SkeletonRenderer` to `ISkeletonRenderer`.
#### 2. Event Changes
- `SkeletonRendererDelegate` type is no longer a nested type in `SkeletonRenderer`.
To fix any compile errors, replace `SkeletonRenderer.SkeletonRendererDelegate` with `SkeletonRendererDelegate`.
- `BeforeApply` delegate type changed from `SkeletonRendererDelegate` to `SkeletonAnimationDelegate`.
- `SkeletonRendererDelegate` type changed from `SkeletonRendererDelegate(SkeletonRenderer)` to `SkeletonRendererDelegate(ISkeletonRenderer)`. This affects events: `OnRebuild`, `OnMeshAndMaterialsUpdated`.
To fix any compile errors, change your method parameter from `SkeletonRenderer` to `ISkeletonRenderer`.
- Moved bone events `UpdateLocal`, `UpdateWorld`, and `UpdateComplete` from `ISkeletonAnimation` classes (`SkeletonAnimation`, `SkeletonMecanim`) to `ISkeletonRenderer classes (SkeletonRenderer, SkeletonGraphic)`. Changed delegate type from `UpdateBonesDelegate` to `SkeletonRendererDelegate`, with parameter `ISkeletonRenderer` instead of `ISkeletonAnimation`.
#### 2. Method Changes
- `LateUpdateMesh()` has been changed to `UpdateMesh()`.
- Removed `MeshGenerator.TryReplaceMaterials`.
#### 3. Execution Order
- `SkeletonRenderer` and `SkeletonGraphic` components received `DefaultExecutionOrder(1)]` which makes them run after default *(order=0)* scripts. This ensures animations are applied before the skeleton is updated even if `UpdateTiming` is set to `InLateUpdate`.
#### 4. Behaviour Changes
- `generateMeshOverride` is now also called when `singleSubmesh` is enabled.
### Field and Property Migration
#### Mesh Generation Settings
| **Old API** | **New API** | **Notes** |
|-------------------|-------------------|-----------|
| `skeletonRenderer.zSpacing` | `skeletonRenderer.MeshSettings.zSpacing` | Moved to MeshSettings |
| `skeletonRenderer.useClipping` | `skeletonRenderer.MeshSettings.useClipping` | Moved to MeshSettings |
| `skeletonRenderer.immutableTriangles` | `skeletonRenderer.MeshSettings.immutableTriangles` | Moved to MeshSettings |
| `skeletonRenderer.pmaVertexColors` | `skeletonRenderer.MeshSettings.pmaVertexColors` | Moved to MeshSettings |
| `skeletonRenderer.tintBlack` | `skeletonRenderer.MeshSettings.tintBlack` | Moved to MeshSettings |
| `skeletonRenderer.addNormals` | `skeletonRenderer.MeshSettings.addNormals` | Moved to MeshSettings |
| `skeletonRenderer.calculateTangents` | `skeletonRenderer.MeshSettings.calculateTangents` | Moved to MeshSettings |
#### Hidden Lowercase Attributes
- `skeletonRenderer.maskInteraction` is replaced by Property `skeletonRenderer.MaskInteraction`.
#### Deprecated Lowercase Attributes
- Lowercase attributes `initialFlipX`, `initialFlipY` and `initialSkinName` are now deprecated and will be removed in future runtime versions. Use the added properties of the same name but uppercase instead: `InitialFlipX`, `InitialFlipY` and `InitialSkinName`.
---
## ▶️ SkeletonAnimation
### Breaking Changes
#### 1. Component Architecture
- **SkeletonAnimation is now a separate component from SkeletonRenderer**, no longer a subclass.
- Access renderer via: `skeletonAnimation.Renderer`.
- Access animation from renderer via: `skeletonRenderer.Animation`.
#### 2. Property Changes
- `state` is no longer public. Use `AnimationState` property instead.
- `valid` removed. Use `IsValid` instead.
#### 3. Method Changes
- Added `UpdateOncePerFrame()` - updates if `Update` has not been called this frame. The existing `Update(float time)` still always updates when called.
- `Update()` without parameters is no longer public, use either `UpdateOncePerFrame()` to update when no update has been performed this frame,
or `Update(0)` to force an animation update.
### Field and Property Migration
As `SkeletonAnimation` is now a separate component, methods and properties provided by `SkeletonRenderer` can no longer be accessed directly via a `SkeletonAnimation` object. There is a `skeletonAnimation.Renderer` property available to access the associated `ISkeletonRenderer` from a `SkeletonAnimation` object,
and an `skeletonRenderer.Animation` property to access the associated `ISkeletonAnimation` from a `SkeletonRenderer` or `SkeletonGraphic` object. For members that are not exposed by the `ISkeletonRenderer` interface, you can cast `skeletonAnimation.Renderer` to `SkeletonRenderer` or `SkeletonGraphic` respectively to access the renderer member variables.
### Example Code
```csharp
// Old SkeletonRenderer property access from SkeletonAnimation
skeletonAnimation.zSpacing = 0.1f;
skeletonAnimation.AnySkeletonRendererProperty;
// New SkeletonRenderer property access from SkeletonAnimation
skeletonAnimation.Renderer.MeshSettings.zSpacing = 0.1f; // exposed in ISkeletonRenderer interface
var skeletonRenderer = (SkeletonRenderer)skeletonAnimation.Renderer;
skeletonRenderer.AnySkeletonRendererProperty; // not exposed in ISkeletonRenderer interface
```
---
## ▶️ SkeletonMecanim
### Breaking Changes
#### 1. Component Architecture
- **SkeletonMecanim is now a separate component from SkeletonRenderer**, no longer a subclass.
- Same access pattern as [SkeletonAnimation](#▶️-skeletonanimation).
#### 2. Method Changes
- `Update()` is no longer public.
- Use `UpdateIfNecessary()` or `Update(0)` to force update.
### Field and Property Migration
Same as [SkeletonAnimation](#▶️-skeletonanimation) above.
---
## ▶️ SkeletonGraphic
### Breaking Changes
#### 1. Component Architecture
- **SkeletonGraphic no longer covers animation, add SkeletonAnimation as a separate animation component**.
- Animation accessed via: `skeletonGraphic.Animation`.
#### 2. Changing Existing References to SkeletonAnimation
If your components are holding a reference to `SkeletonGraphic` only to modify its animation properties, it is recommended to change the reference type to `SkeletonAnimation`.
This way you can access animation state like `skeletonAnimation.AnimationState`
instead of having to cast it like `((SkeletonAnimation)skeletonGraphic.Animation).AnimationState`. Note that if you want to change the name of serialized component variables, you can use the `[FormerlySerializedAs("previousName")]` attribute in front of a variable definition to automatically reassign your existing serialized value.
#### Example Code
```csharp
// Automatically reassign previous serialized values
[FormerlySerializedAs("skeletonGraphic")]
public SkeletonAnimation skeletonAnimation; // Will maintain the reference after upgrade
```
#### 3. Property Changes
- Removed property `AnimationState` - query it from the `SkeletonAnimation` component instead.
- `MeshGenerator` is no longer public - use `MeshSettings` property and `SetMeshSettings()` instead.
- `MaterialsMultipleCanvasRenderers` type changed from `ExposedList<Material>` to `Material[]`.
#### 4. Creation Helper Methods
- `NewSkeletonGraphicGameObject` now creates both `SkeletonGraphic` and `SkeletonAnimation` to maintain existing behaviour. Return type changed to return both component references in a single struct.
- `AddSkeletonGraphicComponent` is removed and replaced by:
- `AddSkeletonGraphicAnimationComponents` - creates both `SkeletonGraphic` and `SkeletonAnimation` components.
- `AddSkeletonGraphicRenderingComponent` - creates only `SkeletonGraphic` component.
#### 5. Event Changes
- Delegate signature changed from `SkeletonRendererDelegate(SkeletonGraphic)` to `SkeletonRendererDelegate(ISkeletonRenderer)`. This affects events: `OnRebuild`, `OnMeshAndMaterialsUpdated`.
To fix any compile errors, change your method parameter from SkeletonGraphic to ISkeletonRenderer.
#### 6. Execution Order
- `SkeletonRenderer` and `SkeletonGraphic` components received `DefaultExecutionOrder(1)]` which makes them run after default *(order=0)* scripts. This ensures animations are applied before the skeleton is updated even if `UpdateTiming` is set to `InLateUpdate`.
#### 7. Behaviour Changes - Material Updates
- Materials at each `CanvasRenderer` are no longer updated every `LateUpdate`, instead they are updated when either:
- a) the updated skeleton requires a change of materials, or
- b) when `CustomMaterialOverride` or `CustomTextureOverride` were accessed and thus potentially modified.
### Field and Property Migration
#### Animation Properties
| **Old API** | **New API** | **Notes** |
|-------------------|-------------------|-----------|
| `skeletonGraphic.AnimationState` | `((SkeletonAnimation)skeletonGraphic.Animation).AnimationState` | Cast required |
| `skeletonGraphic.startingAnimation` | `skeletonAnimation.AnimationName` | Via Animation component |
| `skeletonGraphic.startingLoop` | `skeletonAnimation.loop` | Via Animation component |
| `skeletonGraphic.timeScale` | `skeletonAnimation.timeScale` | Via Animation component |
| `skeletonGraphic.unscaledTime` | `skeletonAnimation.unscaledTime` | Via Animation component |
#### Mesh Generator Settings
| **Old API** | **New API** | **Notes** |
|-------------------|-------------------|-----------|
| `skeletonGraphic.MeshGenerator.settings` | `skeletonGraphic.MeshSettings` | Direct access to settings |
---
## ⚠️ Additional Important Notes
### Preventing Lost Component References
Any references by other components (e.g. `SkeletonRenderSeparator`) that reference a `SkeletonRenderer` component and had a `SkeletonAnimation` or `SkeletonMecanim` target will be pointing to *null* after the upgrade, since the `SkeletonAnimation` and `SkeletonMecanim` components are no longer subclasses of `SkeletonRenderer` and thus no valid reference. The manual solution is to leave the type as `SkeletonRenderer` and lose references to `SkeletonAnimation` (will be set to *none*). Then you need to manually re-assign the lost references in your scenes and prefabs. A semi-automatic alternative solution is as follows: change the type of your `SkeletonRenderer` variable to `Component` (to capture the object reference and not lose it) and add a second variable of type `SkeletonRenderer` (or `SkeletonAnimation`) and then programmatically read it from the `Component` variable and assign it to the newly added variable. You can e.g. do this automatically in the Unity Editor in `Awake()` with an `[ExecuteAlways]` tag added to your component.
#### Example code
```csharp
// Old class before upgrading
public class TestMigrateReferences : MonoBehaviour {
public SkeletonRenderer skeletonRenderer; // this SkeletonAnimation reference assigned here would be lost after upgrading.
public void Foo () {
skeletonRenderer.skeleton.ScaleX = -1;
}
}
// New class after upgrading
[ExecuteAlways] // or [ExecuteInEditMode]
public class TestMigrateReferences : MonoBehaviour {
#if UNITY_EDITOR
[SerializeField, HideInInspector, FormerlySerializedAs("skeletonRenderer")] Component previousSkeletonRenderer; // this captures the old SkeletonAnimation reference assigned at the name skeletonRenderer.
#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
}
```
### Component Enable/Disable
Since `ISkeletonRenderer` and `ISkeletonAnimation` components are now separate, scripts that enable/disable any of these components need adjustment to **enable/disable both**.
### SkeletonUtilityBone Behaviour Change
In mode Override, `SkeletonUtilityBone` no longer adjusts the Transform in `UpdatePhase.World`, only in `UpdatePhase.Complete` (removes redundant update).
### Automatic Migration
- Unity Editor automatically transfers deprecated fields when `AUTO_UPGRADE_TO_43_COMPONENTS` is defined.
- To upgrade all scenes and prefabs at once, go to `Edit - Preferences - Spine` and select `Upgrade Scenes & Prefabs` - `Upgrade All`.
- The `UpgradeTo43` and `TransferDeprecatedFields()` methods in each class handles serialized data migration.
- Manual code updates are still required for runtime access.
### Summary of Most Common Changes
1. **Add `.Renderer.`** prefix to access rendering properties from animation components.
2. **Add `.MeshSettings.`** to access mesh generation settings.
3. **Cast to SkeletonAnimation** when accessing AnimationState from SkeletonGraphic.
4. **Update delegate method signatures** from concrete types to interfaces.
5. **Re-assign lost references** after upgrade using the migration pattern above.
---
## Disabling Automatic Upgrade Checks
Once you have completed the migration of all your Spine assets, scenes, and prefabs, you can disable the automatic upgrade checks to improve editor performance:
1. Go to `Edit → Preferences → Spine`
2. Under `Automatic Component Upgrade`, click `Split Component Upgrade` → `Disable`
This will stop the Unity Editor from performing in-editor checks upon scene or prefab loading to determine whether components need to be migrated. You can re-enable it at any time if you need to migrate additional assets.
---
## Need Help?
If you encounter any unexpected problems during migration or find that component properties are incorrectly migrated, please post on the [Spine forum](https://esotericsoftware.com/forum). We're happy to help and fix any issues to make automatic migration as painless as possible.