1. 程式人生 > >快捷找回UI上Image繫結的spirte元素

快捷找回UI上Image繫結的spirte元素

引言

或許很多同學都遇到一個坑,明明已經完成的一個UI,在很後期一個資源的變動下(例如全部重新打圖集)導致image引用的sprite資源混亂,茫茫多的ui難道需要一個一個重新指定sprite?想著大概都是頭(dan)疼吧。

解決思路

每個UI上都繫結一個指令碼,用來記錄每個image所繫結的sprite的名字。當資源發生變更時,自動根據繫結的sprite的名字自動繫結它目前最新的sprite。

具體步驟

1.在資源發生大變動前進行UI上image的繫結,程式碼如下。

    [MenuItem("Tool/圖集優化工具/步驟一生成image資訊檔案", false, 101)]
    public static void BuildResourceMapping()
    {
        EditorUtility.DisplayProgressBar("生成UI資源對映元件", "", 0);

        try
        {
            Object[] objs = Selection.objects;
            float count = 0;
            foreach (var obj in objs)
            {
                EditorUtility.DisplayProgressBar("生成Image資源對映元件", obj.name, count++ / objs.Length);
                GameObject go = obj as GameObject;
                SpriteTemp temp = go.GetComponent<SpriteTemp>();
                if (temp == null)
                {
                    temp = go.AddComponent<SpriteTemp>();
                }
                temp.Bind();
            }
        }
        catch (System.Exception e)
        {
            Debug.LogError(e);
        }

        AssetDatabase.Refresh();
        AssetDatabase.SaveAssets();
        EditorUtility.ClearProgressBar();
    }
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class SpriteTemp : MonoBehaviour {

    [System.Serializable]
    public class Item
    {
        public GameObject spreiteGO;
        public string spriteName;
    }

    public Item[] items;
    public void Bind()
    {
        Image[] images = GetComponentsInChildren<Image>(true);
        items = new Item[images.Length];
        for (int i = 0; i < images.Length; i++)
        {
            Item item= new Item();
            item.spreiteGO = images[i].gameObject;
            if (images[i].sprite != null)
            {
                item.spriteName = images[i].sprite.name;
                items[i] = item;           
            }
           
        }

    }

}

2.發生資源變動

3.繫結新的sprite

    [MenuItem("Tool/圖集優化工具/步驟2一鍵繫結所有圖片", false, 102)]
    public static void BindImage()
    {

        string source = Application.dataPath + "/SpriteSet/StaticSprite";
        Dictionary<string, Sprite> spriteMapping = new Dictionary<string, Sprite>();
        string[] staticPath = Directory.GetFiles(source, "*.png", SearchOption.AllDirectories);
        int totalSprite = staticPath.Length;
        foreach (string f in staticPath)
        {
            string spriteName = f.Replace(source, "");
            spriteName = spriteName.Replace("\\", "").Replace("/", "");
            string assetPngPath = "Assets" + f.Replace(Application.dataPath, "").Replace("\\", "/");
            Object[] objects = AssetDatabase.LoadAllAssetsAtPath(assetPngPath);
            foreach (var obj in objects)
            {
                Sprite s = obj as Sprite;
                if (s != null)
                {
                    if (!spriteMapping.ContainsKey(s.name))
                    {
                        spriteMapping.Add(s.name, s);
                    }
                }

            }
 
        }
        EditorUtility.DisplayProgressBar("繫結Image資源", "", 0);
        {
            Object[] objs = Selection.objects;
            float count = 0;
            foreach (var obj in objs)
            {
                GameObject prefab = obj as GameObject;
                SpriteTemp spriteTemp = prefab.GetComponent<SpriteTemp>();
                EditorUtility.DisplayProgressBar("繫結Image資源", obj.name, count++ / objs.Length);
                if (obj.GetType() == typeof(GameObject))
                {
                    GameObject go = obj as GameObject;
                    {
                        List<UnityEngine.UI.Image> list = new List<UnityEngine.UI.Image>();
                        GetWidget(go.transform, ref list);
                        foreach (var i in list)
                        {
                            //if (i.sprite == null)
                            {
                                if (spriteTemp != null)
                                {
                                    string spriteName = "";
                                    for (int k = 0; k < spriteTemp.items.Length; k++)
                                    {
                                        if (spriteTemp.items[k] != null)
                                        {
                                            if (spriteTemp.items[k].spreiteGO == i.gameObject)
                                            {
                                                spriteName = spriteTemp.items[k].spriteName;
                                                break;
                                            }
                                        }

                                    }

                                    if (i.sprite == null || i.sprite.name != spriteName)
                                    {
                                        Sprite sprite;
                                        if (spriteName != "")
                                        {
                                            spriteMapping.TryGetValue(spriteName, out sprite);
                                            if (sprite != null)
                                            {
                                                i.sprite = sprite;
                                                i.material = null;
                                            }
                                            else
                                            {
                                                Debug.LogError("找不到圖片:" + spriteName);
                                            }
                                        }
                                    }
                                }
                            }

                        }
                    }
                }
            }
        }
        AssetDatabase.Refresh();
        AssetDatabase.SaveAssets();
        EditorUtility.ClearProgressBar();
    }

4.對UI的prefab進行批處理的apply(需要將UI的prefab拖到場景)

 [UnityEditor.MenuItem("Tool/Apply Selected Prefabs")]
    static void ApplySelectedPrefabs()
    {
        //獲取選中的gameobject物件  
        GameObject[] selectedsGameobject = Selection.gameObjects;

        GameObject prefab = PrefabUtility.FindPrefabRoot(selectedsGameobject[0]);

        for (int i = 0; i < selectedsGameobject.Length; i++)
        {
            GameObject obj = selectedsGameobject[i];

            UnityEngine.Object newsPref = PrefabUtility.GetPrefabObject(obj);

            //判斷選擇的物體,是否為預設  
            if (PrefabUtility.GetPrefabType(obj) == PrefabType.PrefabInstance)
            {

                UnityEngine.Object parentObject = PrefabUtility.GetPrefabParent(obj);
                //獲取路徑  
                //string path = AssetDatabase.GetAssetPath(parentObject);  
                //Debug.Log("path:"+path);  
                //替換預設  
                PrefabUtility.ReplacePrefab(obj, parentObject, ReplacePrefabOptions.ConnectToPrefab);
                //重新整理  
                AssetDatabase.Refresh();
            }


        }
    }

後記

程式碼匆忙寫上,沒有太高的質量,僅供參考。