zoukankan      html  css  js  c++  java
  • Unity3D-NGUI动态加载图片

    NGUI提供了很方便的UIAtlas,其主要作用是改进DrawCall,把众多图片整合在一张贴图上,由于UNITY3D简单易用的好处,所以只是用原生的GUI很容易忽视DrawCall的问题,所以NGUI为了改进,才有了UIAtlas。当然NGUI还做了很多优化。

    这里主要还是介绍如何利用UISprite来动态的加载图片。NGUI所提供的UIAtlas虽然好用,但只能在Editor内生成贴图和prefab以供UISprite使用。为了能够让游戏资源与游戏本体尽可能的分离,特别是游戏资源需要动态更新的情况。很多时候,都需要动态加载,动态设置UIAtlas。

    这里主要介绍2个方法。

    方法1:直接在代码中创建和设置UIAtlas并对UISprite进行显示。这种方法可以对任何零散的贴图进行加载,但缺点是浪费DrawCall,主要应用在特别零散的贴图资源上。

    public class ImageLoader : MonoBehaviour {
        
        //需要加载动态图片的对象
        public UISprite m_img;
        //自用的Atlas
        private UIAtlas m_uiAtlas;
        /// <summary>
        /// 加载的贴图
        /// </summary>
        /// <param name="tex">Tex.</param>
        public void ImageLoad(Texture2D tex)
        {
            if(tex == null)
            {
                return;    
            }
            if(tex.name == m_img.spriteName)
            {
                return;    
            }
            //准备对象和材质球
            if(m_uiAtlas == null)
            {
                Material mat;
                Shader shader = Shader.Find("Unlit/Transparent Colored");
                mat = new Material(shader);
                m_uiAtlas = this.gameObject.AddComponent<UIAtlas>();
                m_uiAtlas.spriteMaterial = mat;
            }
            //设定贴图
            m_uiAtlas.spriteMaterial.mainTexture = tex;
            m_uiAtlas.coordinates = UIAtlas.Coordinates.Pixels;
            //为对应UISprite接口,给Atlas加对象
            UIAtlas.Sprite sprite = new UIAtlas.Sprite();
            sprite.name = tex.name;
            sprite.outer = sprite.inner = new Rect(0f, 0f, tex.width, tex.height);
            m_uiAtlas.spriteList.Clear();
            m_uiAtlas.spriteList.Add(sprite);
            //设置完成
            m_img.atlas = m_uiAtlas;
            m_img.spriteName = tex.name;
        }
    }

    方法2:将整个UIAtlas及其贴图打包,而后形成资源,驻留在内存中(仅仅是指向资源的指针),UNITY3D会根据引用来确定贴图是否直接放实际内存中。这种方法更适合ICON之类有规律可以配置整合的资源。缺点是需要维护。

    //从资源文件夹加载打包成assetBundle的ICON资源文件
        private IEnumerator LoadResIcon()
        {
            //准备好资源们
            string strFormat = ResourcePath.GetPath() + "UI/{0}";
            string strFilePath = "";
            for(int i = 0 , nMax = GameConfig.Instance.IconSet.strIcons.Length; i < nMax ; i++)
            {
                string strAssetName = GameConfig.Instance.IconSet.strIcons[i];
                
                strFilePath = string.Format(strFormat, strAssetName);
                WWW tmp_www = null;
                try
                {
                    tmp_www = new WWW(strFilePath);
                }
                catch
                {
                    tmp_www = null;
                }
                if(tmp_www==null)
                {
                    continue;
                }    
                yield return tmp_www;
                if(tmp_www.error !=null)
                {
                    tmp_www.Dispose();
                    tmp_www = null;
                    yield break;
                }
                AssetBundle tmp_assetBundle = tmp_www.assetBundle;
                tmp_www.Dispose();
                tmp_www = null;
            
                UIAtlas atlas = tmp_assetBundle.Load(strAssetName,typeof(UIAtlas)) as UIAtlas;
                tmp_assetBundle.Unload(false);
                
                GameConfig.Instance.IconSet.SaveUIAtlas(i, atlas);
            }
            yield return null;
        }

    管理UIAtlas

    public class IconSet
    {
        public string[] strIcons = 
        {
            "A1_Atlas",
            "A2_Atlas",
            "A3_Atlas",
        };
        public UIAtlas[] m_AtlasData;
        Dictionary<string, int> m_dicIcon;
        public IconSet()
        {
            m_AtlasData = new UIAtlas[strIcons.Length];
            m_dicIcon = new Dictionary<string, int>();
        }
        //保存Atlas的完整信息
        public void SaveUIAtlas(int nIndex, UIAtlas UIvalue)
        {
            m_AtlasData[nIndex] = UIvalue;
            foreach (string iconNames in UIvalue.GetListOfSprites())
            {
                m_dicIcon[(string)iconNames.Clone()] = nIndex;//将所有的ICONNAME信息记录并且绑定成索引,以便查找
            }
        }
        //根据ICONNAME找出对应UIATLAS
        public UIAtlas FindAtlasBySpriteName(string name)
        {
            int nAtlasIndex = 0;
            if (m_dicIcon.TryGetValue(name, out nAtlasIndex))
            {
                return m_AtlasData[nAtlasIndex];
            }
            return null;
        }
    }

    实际使用的范例:

    //设置显示对象
    UISprite sprite = this.GetComponent<UISprite>();
    sprite.atlas = GameConfig.Instance.IconSet.FindAtlasBySpriteName("Icon001");
    sprite.spriteName = "Icon001";

    总结:

      以上两种方法基本能够应对大部分UI的现实问题,ImageLoader本身传入的是Texture2D,所以,即便是RenderTexture也没问题,都能与NGUI和谐相处。加以扩展的话,就是让另一个摄像机导出的东西和当前NGUI摆的UI结合。

  • 相关阅读:
    javascript 操作DOM元素样式
    javascript 对象
    javascript 事件对象
    javascript 常用尺寸属性
    团队编程项目作业3-模块开发过程
    buuctf-misc 基础加密
    buuctf-misc 你竟然赶我走
    buuctf-misc 大白
    buuctf-misc N种方法解决
    buuctf-misc二维码
  • 原文地址:https://www.cnblogs.com/oplusx/p/3554960.html
Copyright © 2011-2022 走看看