The information here may change over time as the implementations within Spine-Unity get updated, improved or fixed. This contains intermediate-level documentation. If you're just starting out, try the Getting Started document.
Documentation last updated for Spine-Unity for Spine 3.7.x
If this documentation contains mistakes or doesn't cover some questions, please feel to open an issue or post in the official Spine-Unity forums.
This document is for miscellaneous questions and answers that haven't found a place in an independent page yet.
The console will usually give you an error that looks like this if you have missing using directive on top of your code.
Assets/MyFirstSpineScript.cs(12,9): error CS0246: The type or namespace name `SkeletonAnimation' could not be found. Are you missing `Spine.Unity' using directive?
This is because Spine classes are defined in the Spine
and Spine.Unity
and namespaces.
To tell the compiler which namespaces to use to look for Spine classes, you need to add using directives.
In Unity code, your script should look like this on top:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// These namespaces are for Spine classes.
using Spine;
using Spine.Unity;
public class MyFirstSpineScript : MonoBehaviour {
//....
}
To learn the basics of Unity scripting, see the official Unity Tutorials Scripting Section: https://unity3d.com/learn/tutorials/s/scripting
For more in-depth information on using namespaces in C#, see the official Microsoft documentation: https://docs.microsoft.com/en-us/dotnet/articles/csharp/programming-guide/namespaces/using-namespaces
Sometimes, it may make sense to create Spine GameObjects from code instead of creating prefabs.
To do that, use the NewSkeletonAnimationGameObject
static function. This is actually a convenience method for SkeletonRenderer.NewSpineGameObject<SkeletonAnimation>()
. Calling the latter will return the same thing.
//SkeletonDataAsset skeletonDataAsset; // A reference to your asset
var newSkeletonAnimation = SkeletonAnimation.NewSkeletonAnimationGameObject(skeletonDataAsset);
If you want to create a SkeletonGraphic from code, you need to do use SkeletonGraphic.NewSkeletonGraphicGameObject
instead.
//SkeletonDataAsset skeletonDataAsset; // A reference to your asset
//Transform canvasTransform;
var newSkeletonGraphic = SkeletonGraphic.NewSkeletonGraphicGameObject(skeletonDataAsset, canvasTransform);
SkeletonDataAsset and AtlasAsset provide static functions to create new instances at runtime. This sometimes makes sense if you have on-demand assets where having the extra assets would just be unnecessary data.
See the code below:
using UnityEngine;
using Spine;
using Spine.Unity;
public class RuntimeInstantiationSamples : MonoBehaviour {
public TextAsset skeletonJson;
public TextAsset atlasText;
public Texture2D[] textures;
public Material materialPropertySource;
AtlasAsset runtimeAtlasAsset;
SkeletonDataAsset runtimeSkeletonDataAsset;
SkeletonAnimation runtimeSkeletonAnimation;
void CreateRuntimeAssetsAndGameObject () {
// 1. Create the AtlasAsset (needs atlas text asset and textures, and materials/shader);
// 2. Create SkeletonDataAsset (needs json or binary asset file, and an AtlasAsset)
// 3. Create SkeletonAnimation (needs a valid SkeletonDataAsset)
runtimeAtlasAsset = AtlasAsset.CreateRuntimeInstance(atlasText, textures, materialPropertySource, true);
runtimeSkeletonDataAsset = SkeletonDataAsset.CreateRuntimeInstance(skeletonJson, runtimeAtlasAsset, true);
runtimeSkeletonAnimation = SkeletonAnimation.NewSkeletonAnimationGameObject(runtimeSkeletonDataAsset);
}
}
Yes. After being loaded, each renderable attachment stores a reference to its AtlasRegion and the Material needed to render it.
After your SkeletonData is loaded, you can change the Attachment's AtlasRegion properties to point to a different AtlasPage and Material.
(MeshAttachment/RegionAttachment)renderableAttachment
.(AtlasPage)RendererObject
.(AtlasPage)page
.(Material)RendererObject
Sample MonoBehaviour Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Spine;
using Spine.Unity;
using Spine.Unity.Modules.AttachmentTools;
public class ChangeAttachmentMaterialExample : MonoBehaviour {
public Material customMaterial;
public SkeletonDataAsset skeletonDataAsset;
[SpineSlot] public string slotName;
[SpineSkin] public string skinName;
[SpineAttachment(skinField = "skinName", slotField = "slotName")]
public string attachmentName;
void Start () {
Attachment myAttachment = FindAttachment(skeletonDataAsset, skinName, slotName, attachmentName);
//if (myAttachment == null) return;
SetAttachmentRegionMaterial(myAttachment, customMaterial);
}
static public Attachment FindAttachment (SkeletonDataAsset skeletonDataAsset, string skinName, string slotName, string attachmentName) {
if (skeletonDataAsset == null) throw new System.ArgumentNullException("skeletonDataAsset");
var skeletonData = skeletonDataAsset.GetSkeletonData(true);
//if (skeletonData == null) return null;
var skin = skeletonData.FindSkin(skinName);
//if (skin == null) return null;
int slotIndex = skeletonData.FindSlotIndex(slotName);
//if (slotIndex <= 0) return null;
var attachment = skin.GetAttachment(slotIndex, attachmentName);
return attachment;
}
/// <summary>
/// Creates a new AtlasPage from the given Material, and uses it to modify the given Attachment's AtlasRegion. This method will affect all skeletons using this Attachment.</summary>
static public void SetAttachmentRegionMaterial (Attachment attachment, Material material) {
if (attachment == null) return;
var atlasRegion = GetAttachmentAtlasRegion(attachment);
if (atlasRegion == null) return;
var atlasPage = material.ToSpineAtlasPage(); // extension from Spine.Unity.Modules.AttachmentTools
atlasRegion.page = atlasPage;
}
/// <summary>
/// Gets a reference to an Attachment's AtlasRegion. Will return null if an attachment is not renderable.</summary>
static public AtlasRegion GetAttachmentAtlasRegion (Attachment attachment) {
AtlasRegion atlasRegion = null;
var regionAttachment = attachment as RegionAttachment;
if (regionAttachment != null) {
atlasRegion = (AtlasRegion)regionAttachment.RendererObject;
} else {
var meshAttachment = attachment as MeshAttachment;
if (meshAttachment != null)
atlasRegion = (AtlasRegion)meshAttachment.RendererObject;
}
return atlasRegion;
}
}
SkeletonAnimation.CustomSlotMaterials is a dictionary where you can assign special materials to slots.
By giving it a slot reference and a material reference, it will use that material whenever it needs to render that slot.
GetComponent<SkeletonAnimation>().CustomSlotMaterials[(Slot)mySlot] = (Material)myMaterial;
To remove this replacement, you can use the dictionary's Remove method.
GetComponent<SkeletonAnimation>().CustomSlotMaterials.Remove((Slot)mySlot);
I want to change the materials used to render this one Skeleton. But I don't want to affect other Skeletons.
SkeletonAnimation.CustomMaterialOverride
is a dictionary where you can allow your renderer to use a new Material instead of the original one that would normally be used.
You give it both a reference to the original Material, and the Material that you want to replace it.
GetComponent<SkeletonAnimation>().CustomMaterialOverride[originalMaterial] = newMaterial;
To remove this replacement, you can use the Remove method.
GetComponent<SkeletonAnimation>().CustomMaterialOverride.Remove(originalMaterial);