一、准备工作
Spine插件及基本知识可查看这篇文章:Unity | Spine动画记录-CSDN博客
二、Spine资源动态加载
1.官方说明
官方文档指出不建议这种操作。但spine-unity API允许在运行时从SkeletonDataAsset或甚至直接从三个导出的资产实例化SkeletonAnimation和SkeletonGraphic GameObjects。
2.注意事项
注意:动态加载的三个文件需要命名,并且不能出错。因为源代码中需要用名称来匹配。如下方的代码中要求pageName与贴图name一致,不能有后缀。
public static SpineAtlasAsset CreateRuntimeInstance (TextAsset atlasText, Texture2D[] textures, Material materialPropertySource, bool initialize) {
// Get atlas page names.
string atlasString = atlasText.text;
atlasString = atlasString.Replace("\r", "");
string[] atlasLines = atlasString.Split('\n');
var pages = new List<string>();
for (int i = 0; i < atlasLines.Length - 1; i++) {
if (atlasLines[i].Trim().Length == 0)
pages.Add(atlasLines[i + 1].Trim().Replace(".png", ""));
}
// Populate Materials[] by matching texture names with page names.
var materials = new Material[pages.Count];
for (int i = 0, n = pages.Count; i < n; i++) {
Material mat = null;
// Search for a match.
string pageName = pages[i];
for (int j = 0, m = textures.Length; j < m; j++) {
if (string.Equals(pageName, textures[j].name, System.StringComparison.OrdinalIgnoreCase)) {
// Match found.
mat = new Material(materialPropertySource);
mat.mainTexture = textures[j];
break;
}
}
if (mat != null)
materials[i] = mat;
else
throw new ArgumentException("Could not find matching atlas page in the texture array.");
}
// Create AtlasAsset normally
return CreateRuntimeInstance(atlasText, materials, initialize);
}
3.代码实现
using Spine.Unity;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
public class DownloadSpine : MonoBehaviour
{
public Shader shader;//选择Spine/Skeleton shader
private TextAsset skeletonJson;//json或者二进制文件
private TextAsset atlasText;
private Texture2D[] textures;
private float delay = 0;
private string skinName="base";
private string animationName = "gun toss";
private SpineAtlasAsset runtimeAtlasAsset;
private SkeletonDataAsset runtimeSkeletonDataAsset;
private SkeletonAnimation runtimeSkeletonAnimation;
void Start()
{
StartCoroutine(DownloadFile("https://static0.***.com/ziliao/spineboy-unity/", "spineboy.atlas", "spineboy", "spineboy-unity"));
}
private IEnumerator DownloadFile(string dir, string atlasTextName, string imageName, string skeletonJsonName)
{
//下载atlasText
UnityWebRequest request = UnityWebRequest.Get(dir + atlasTextName + ".txt");
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
{
atlasText = new TextAsset(request.downloadHandler.text);
atlasText.name = atlasTextName;
}
else
{
Debug.LogError("Error downloading atlasText asset: " + request.error);
}
//下载textures
request = UnityWebRequestTexture.GetTexture(dir + imageName + ".png");
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
{
textures = new Texture2D[1];
textures[0] = DownloadHandlerTexture.GetContent(request);
textures[0].name = imageName;
}
else
{
Debug.LogError("Error downloading image asset: " + request.error);
}
//下载skeletonFile
request = UnityWebRequest.Get(dir + skeletonJsonName + ".json");
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
{
skeletonJson = new TextAsset(request.downloadHandler.text);
skeletonJson.name = skeletonJsonName;
}
else
{
Debug.LogError("Error downloading json asset: " + request.error);
}
StartCoroutine(PlayAnim());
}
void CreateRuntimeAssetsAndGameObject()
{
Material material = new Material(shader);
runtimeAtlasAsset = SpineAtlasAsset.CreateRuntimeInstance(atlasText, textures, material, true);
runtimeSkeletonDataAsset = SkeletonDataAsset.CreateRuntimeInstance(skeletonJson, runtimeAtlasAsset, true);
}
IEnumerator PlayAnim()
{
CreateRuntimeAssetsAndGameObject();
if (delay > 0)
{
runtimeSkeletonDataAsset.GetSkeletonData(false);
yield return new WaitForSeconds(delay);
}
runtimeSkeletonAnimation = SkeletonAnimation.NewSkeletonAnimationGameObject(runtimeSkeletonDataAsset);
runtimeSkeletonAnimation.transform.position = new Vector3(0, -3, 0);
// additional initialization
runtimeSkeletonAnimation.Initialize(false);
if (skinName != "")
{
runtimeSkeletonAnimation.Skeleton.SetSkin(skinName);
}
runtimeSkeletonAnimation.Skeleton.SetSlotsToSetupPose();
if (animationName != "")
{
runtimeSkeletonAnimation.AnimationState.SetAnimation(0, animationName, true);
}
}
}