快捷找回UI上Image繫結的spirte元素
阿新 • • 發佈:2019-02-14
引言
或許很多同學都遇到一個坑,明明已經完成的一個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();
}
}
}
後記
程式碼匆忙寫上,沒有太高的質量,僅供參考。