UGUI -- 原生Sprite 处理小扩展

来源:互联网 发布:试客系统整站源码 编辑:程序博客网 时间:2024/04/30 05:58

使用了Unity5.0 之后的版本,做UI界面再也不想用第三方的UI插件了,毕竟支持比较好!但也有很多不足的地方,比如Sprite的使用,系统没有提供根据Sprite名称获取Sprite的方法,所以一开始我是直接把Sprite的路径保存在文件里面,使用的时候Resources.Load一下,这样做每次修改都要更新文件,很麻烦,而且当Sprite超多的时候就更加麻烦了,NGUI和2Dtoolkit里都有图集的概念来管理这些Sprite,但是原生的是没有的!一开始自己的想法是把每张Sprite保存到Prefab里面,百度一下,原来雨松MOMO大神也有这么介绍,他的文章地址点击打开链接;好,既然思路正确,虽然雨松MOMO也有给出了代码,不过还是要自己按照自己的风格写一遍,哈哈哈!

首先写一个UIAtlas类,直接盗用NGUI的名称,不要介哈,这个类主要提供根据名称获取Sprite的接口!主要代码如下:


public class UIAtlas : MonoBehaviour{   private Dictionary<string, Sprite> spriteDictionary = new Dictionary<string, Sprite>();    private bool isInit = false;    void Awake()    {        InitSprites();    }    void InitSprites()    {        if (!isInit)        {            SpriteRenderer[] renders = GetComponentsInChildren<SpriteRenderer>();            foreach (var render in renders)            {                if (!spriteDictionary.ContainsKey(render.name))                {                    spriteDictionary.Add(render.sprite.name, render.sprite);                }            }            isInit = true;        }    }    public Sprite Load(string spriteName)    {        InitSprites();        if (spriteDictionary.ContainsKey(spriteName))        {            return spriteDictionary[spriteName];        }        else        {            Debug.LogError("Sprite[" + spriteName + "] do not exist!");        }        return null;    }    public bool HasSprite(string spriteName)    {        InitSprites();        return spriteDictionary.ContainsKey(spriteName);    }} 

那么我们在建立预设体的时候就要挂上这个脚本,然后把所有你要加入到这个图集的Sprite生成一个子物体,把Sprite引用到子物体上,好,是不是很简单!不过如果我们都要自己手动来把所有的Sprite都建立一个子物体也会让人崩溃,所以下面我给出一个Editor下的不完善的小工具,同时上面UIAtlas 类会增加以下在Editor下的接口


#if UNITY_EDITOR    public void AddSprite(Sprite sprite)    {        GameObject go = new GameObject(sprite.name);        SpriteRenderer sr = go.AddComponent<SpriteRenderer>();        sr.sprite = sprite;        go.transform.parent = transform;        go.transform.ResetLocal();    }    public Dictionary<string, Sprite> GetSprites() {        Dictionary<string, Sprite> ret = new Dictionary<string, Sprite>();        SpriteRenderer[] renders = GetComponentsInChildren<SpriteRenderer>();        foreach (var render in renders)        {            if (!ret.ContainsKey(render.name))            {                ret.Add(render.sprite.name, render.sprite);            }        }        return ret;    }    public void RemoveSprite(string name)    {        SpriteRenderer[] renders = GetComponentsInChildren<SpriteRenderer>();        foreach (var render in renders)        {            if(render.name == name)            {                DestroyImmediate(render.gameObject);            }        }    }#endif

扩展界面如下:






嗯,有点熟悉!这个就是我用来管理我自己的的图集的,只要我们把新建立的绑定有UIAtlas脚本的预设体拖到上面Atals的位置,再在资源文件夹里选中你要添加到里面去的Sprite就行,大概效果是这样




然后点击最底下 Add/Update 按钮就会生成包含上面两个Sprite的Prefab啦,如下:




OK,到这里就算完成了!至于这个扩展怎么写的我就不多说了,我对Editor下编写扩展也不太熟悉,这也是我生搬硬套搞出来的!代码还是贴上来,如下:


using System;using System.Collections.Generic;using System.Linq;using System.Text;using UnityEditor;using UnityEngine;public class CreateAtlasWindow : EditorWindow{    class SpriteData    {        public SpriteData(string name, Sprite sprite)        {            this.Sprite = sprite;            this.SpriteName = name;        }        public string SpriteName;        public Sprite Sprite;        public bool IsChange = true;    }    [MenuItem("ExtensionTools/Open Atlas Window")]    static void Init()    {        CreateAtlasWindow window = GetWindow<CreateAtlasWindow>();    }    public UIAtlas uiAtlas = null;    private Dictionary<string,SpriteData> sprites = new Dictionary<string, SpriteData>();    private Vector2 pos;    void OnGUI()    {        if (Selection.activeObject)        {                     Sprite sprite = Selection.activeObject as Sprite;            if(sprite)            {                if (!sprites.ContainsKey(sprite.name))                {                    sprites.Add(sprite.name, new SpriteData(sprite.name, sprite));                }                else                {                    if(sprites[sprite.name].Sprite != sprite)                    {                        sprites[sprite.name].Sprite = sprite;                        sprites[sprite.name].IsChange = true;                    }                }            }        }        EditorGUILayout.BeginVertical();        float posX = 10;        float posY = 10;        Rect rect = new Rect(posX, posY, 500, 20);        uiAtlas = EditorGUI.ObjectField(rect, new GUIContent("Atlas:"), uiAtlas, typeof(UIAtlas), false) as UIAtlas;        if (uiAtlas)        {            foreach(var item in uiAtlas.GetSprites())            {                if (!sprites.ContainsKey(item.Key))                {                    sprites.Add(item.Key, new SpriteData(item.Key, item.Value));                }            }        }        else        {            sprites.Clear();        }        posY += 20;        rect = new Rect(posX, posY, 100, 50);        GUILayout.BeginArea(rect);        using (var h = new EditorGUILayout.HorizontalScope("Button"))        {            if (GUI.Button(h.rect, GUIContent.none))            {                CreateNewAtlas();            }            GUIStyle style = new GUIStyle();            style.alignment = TextAnchor.MiddleCenter;            GUILayout.Label("New Atlas", style);        }        GUILayout.EndArea();        posY += 50;        pos = EditorGUILayout.BeginScrollView(new Vector2(posX, posY));         GUILayout.BeginArea(new Rect(pos, new Vector2(600, 250)));                EditorGUILayout.BeginVertical();        List<string> curSprites = new List<string>(sprites.Keys);        foreach (var sp in curSprites)        {            EditorGUILayout.BeginHorizontal();            EditorGUILayout.TextField("Sprite:", sp, GUILayout.Width(500));                        if(GUILayout.Button(new GUIContent("Delete")))            {                sprites.Remove(sp);                DeleteSprite(sp);            }            EditorGUILayout.EndHorizontal();        }        EditorGUILayout.EndVertical();        GUILayout.EndArea();        EditorGUILayout.EndScrollView();        using (var h = new EditorGUILayout.HorizontalScope("Button"))        {            if (GUI.Button(h.rect, GUIContent.none))            {                if (uiAtlas)                {                    AddOrUpdateAtlas(uiAtlas.name);                }                else                {                    Debug.LogError("Atlas can't be null!");                }            }            GUIStyle style = new GUIStyle();            style.alignment = TextAnchor.MiddleCenter;            GUILayout.Label("Add/Update", style);        }        EditorGUILayout.EndVertical();        this.Repaint();    }    void AddOrUpdateAtlas(string name)    {        GameObject newPrefabs = new GameObject(name);        UIAtlas atlas = newPrefabs.AddComponent<UIAtlas>();        foreach(var sp in sprites)        {            atlas.AddSprite(sp.Value.Sprite);        }        GameObject go = PrefabUtility.ReplacePrefab(newPrefabs, uiAtlas, ReplacePrefabOptions.Default);        uiAtlas = go.GetComponent<UIAtlas>();        DestroyImmediate(newPrefabs);    }    void CreateNewAtlas()    {        GameObject go = new GameObject("New Atlas");        UIAtlas uiAtlas = go.AddComponent<UIAtlas>();                GameObject newGo = PrefabUtility.CreatePrefab("Assets/NewAtlas.prefab", go);        DestroyImmediate(go);        this.uiAtlas = newGo.GetComponent<UIAtlas>();    }    void DeleteSprite(string sprite)    {        Debug.Log("DeleteSprite");        GameObject go = Instantiate(this.uiAtlas.gameObject);        UIAtlas uia = go.GetComponent<UIAtlas>();        if (uia.HasSprite(sprite))        {            uia.RemoveSprite(sprite);            GameObject last = PrefabUtility.ReplacePrefab(go, uiAtlas, ReplacePrefabOptions.Default);            this.uiAtlas = last.GetComponent<UIAtlas>();        }        DestroyImmediate(go);    }}
                                             
0 0
原创粉丝点击