unity 在代碼中創建spine動畫組件

  項目中用到了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了。


到此,問題解決。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章