unity 在代码中创建spine动画组件

19 篇文章 0 订阅

  项目中用到了spine动画,使用Assetbundle打包后,在手机上运行会出现丢材质的情况。如果不进行打包,直接放到Resources目录下是可以正常加载的,但是,这样包就会很大,而且也不能进行热更新。进过测试,发现在代码中创建spine组件是可以解决这个问题,于是就有了下面的方案。

 

我们先说方案,再说问题。

方案:

spine动画制作人员提供的spine动画三个文件分别是.json,.atlas,.png,把这三个文件放到unity(我用的unity版本是5.3.4f1)中,会自动生成atlas.asset,.mat,skeletondata.asset三个文件,我们只使用.mat文件,因为mat文件上已经关联了.png文件,所以我们实际要打包的文件是三个源文件.json,.atlas,.png和.mat文件,而.png文件实际上是作为.mat的依赖打包的,下面在代码中创建spine组件如下:

 

GameObject addSpineComponent(UnityEngine.Object obj)

    {

        GameObject go = GameObject.Instantiate(obj) as GameObject;

        go.name = obj.name;

        GameObject.DontDestroyOnLoad(go);

 

        SkeletonAnimation sa;

        SkeletonDataAsset sda;

 

        sda = ScriptableObject.CreateInstance<SkeletonDataAsset>();

        sda.fromAnimation = new string[0];

        sda.toAnimation = new string[0];

        sda.duration = new float[0];

        sda.scale = 0.01f;

        sda.defaultMix = 0.15f;

      //SpineNameInfo中存着.json,.atlas,.mat的名称

        SpineNameInfo sni = dicMonsterSpineInfos[go.name];

 

        AtlasAsset[] arrAtlasData = new AtlasAsset[sni.AtlasFileNames.Length];

        for (int i = 0; i < arrAtlasData.Length; i++)

        {

            string atlasFileName = sni.AtlasFileNames[i];

            AtlasAsset atlasdata = ScriptableObject.CreateInstance<AtlasAsset>();

            atlasdata.atlasFile = GetObj(atlasFileName) as TextAsset;

            string[] mNames = sni.GetMaterialNames(atlasFileName);

            atlasdata.materials = new Material[mNames.Length];

            for (int j = 0; j < mNames.Length; j++)

            {

                //Material m  = dicPreloadAssets[mNames[j]] as Material;

                atlasdata.materials[j] = GetObj(mNames[j]) as Material;

            }

 

            //atlasdata.materials = mats;

            atlasdata.Reset();

            arrAtlasData[i] = atlasdata;

        }

 

        sda.atlasAssets = arrAtlasData;

        sda.skeletonJSON = GetObj(sni.JsonFileName) as TextAsset;

 

        sa = go.AddComponent<SkeletonAnimation>();

        sa.skeletonDataAsset = sda;

        sa.calculateNormals = true;

        sa.skeletonDataAsset.Reset();

        sa.AnimationName = "run";

        sa.loop = true;

 

        sa.Initialize(false);

 

        return go;

    }

 

    public class SpineNameInfo

    {

        private Dictionary<string, string[]> dicAtlasFileNames = new Dictionary<string, string[]>();

      //.json文件名

        public string JsonFileName = string.Empty;

      //.atlas文件名,可能有多个.atlas文件(虽然我的项目中只有一个)

        public string[] AtlasFileNames

        {

            get

            {

                string[] s = new string[dicAtlasFileNames.Count];

                dicAtlasFileNames.Keys.CopyTo(s, 0);

                return s;

            }

        }

 

      //.mat文件名,可能有多个mat文件

        public string[] GetMaterialNames(string atlasFileName)

        {

            if (dicAtlasFileNames.ContainsKey(atlasFileName))

                return dicAtlasFileNames[atlasFileName];

            return new string[0];

        }

 

        public void Add(string atlasFileName, string[] m)

        {

            if (!dicAtlasFileNames.ContainsKey(atlasFileName))

                dicAtlasFileNames.Add(atlasFileName, m);

        }

    }

 

   //这里是我项目中用到的对象池,根据资源名,获取资源对象

    public UnityEngine.Object GetObj(string name)

    {

        if (pool.ContainsKey(name))

            return pool[name];

        return null;

    }

 

可能您会注意到,怎么没有.png文件呢,我刚才在上面也提到,png文件会作为mat文件的依赖打包进assetbundle,所以在加载mat文件的时候png自然也已经被加载好了。

 

  以上是我的解决方案。可能有点乱,如果有什么不明白的,我再提供两个链接,也是网上的一些解决方案。

 

http://answers.unity3d.com/questions/710571/spine-creating-spine-skeletonanimation-using-cscri.html

 

http://zh.esotericsoftware.com/forum/Creating-Spine-SkeletonAnimation-using-c-3091

 

下面说一下问题:

使用上述方案以后,发现一个问题,就是创建spine动画很耗时。因为有大量的怪物要创建,这样就导致原先的场景预加载时间很长,长到不能接受。好在虽然怪物数量庞大,但种类不是很多,复用也很高,所以就把spine动画的创建和预加载放到了游戏数据初始化中,时间虽然会有点长,但因为游戏刚开始初始化的东西不多,就还能接受,后面再加载场景怪物的时候,直接获取预加载的种类的对象,然后实例化就OK了。

 

到此,问题解决。

转载于:https://blog.51cto.com/chenshuhb/1836481

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity循环播放Spine动画代码可以参考下面的示例代码: ``` using System.Collections; using System.Collections.Generic; using UnityEngine; using Spine.Unity; public class SpineAnimationController : MonoBehaviour { // Spine动画组件 public SkeletonAnimation skeletonAnimation; // Spine动画名称 public string animationName; // 是否循环播放 public bool loop = true; // Start is called before the first frame update void Start() { // 播放Spine动画 skeletonAnimation.AnimationState.SetAnimation(0, animationName, loop); } // Update is called once per frame void Update() { // 如果Spine动画播放结束,则重新播放 if (skeletonAnimation.AnimationState.GetCurrent(0).IsComplete) { skeletonAnimation.AnimationState.SetAnimation(0, animationName, loop); } } } ``` 在上面的示例代码,我们首先定义了一个SkeletonAnimation类型的变量skeletonAnimation,它是Spine动画组件,用于播放Spine动画。我们还定义了一个字符串类型的变量animationName,它是Spine动画的名称。我们还定义了一个布尔类型的变量loop,用于指定是否循环播放Spine动画。 在Start函数,我们调用了skeletonAnimation.AnimationState.SetAnimation函数来播放Spine动画。其,第一个参数0表示Spine动画的TrackIndex,第二个参数animationName表示要播放的Spine动画的名称,第三个参数loop表示是否循环播放Spine动画。 在Update函数,我们检查当前播放的Spine动画是否已经播放完毕,如果已经播放完毕,则重新播放Spine动画

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值