Unity3D-NGUI動(dòng)態(tài)加載圖片 - OpLusX
NGUI提供了很方便的UIAtlas,其主要作用是改進(jìn)DrawCall约郁,把眾多圖片整合在一張貼圖上,由于UNITY3D簡(jiǎn)單易用的好處咧织,所以只是用原生的GUI很容易忽視DrawCall的問題萧豆,所以NGUI為了改進(jìn),才有了UIAtlas邻寿。當(dāng)然NGUI還做了很多優(yōu)化蝎土。
這里主要還是介紹如何利用UISprite來(lái)動(dòng)態(tài)的加載圖片。NGUI所提供的UIAtlas雖然好用绣否,但只能在Editor內(nèi)生成貼圖和prefab以供UISprite使用誊涯。為了能夠讓游戲資源與游戲本體盡可能的分離,特別是游戲資源需要?jiǎng)討B(tài)更新的情況蒜撮。很多時(shí)候暴构,都需要?jiǎng)討B(tài)加載,動(dòng)態(tài)設(shè)置UIAtlas段磨。
這里主要介紹2個(gè)方法取逾。
方法1:直接在代碼中創(chuàng)建和設(shè)置UIAtlas并對(duì)UISprite進(jìn)行顯示。這種方法可以對(duì)任何零散的貼圖進(jìn)行加載苹支,但缺點(diǎn)是浪費(fèi)DrawCall砾隅,主要應(yīng)用在特別零散的貼圖資源上。
public class ImageLoader : MonoBehaviour {
//需要加載動(dòng)態(tài)圖片的對(duì)象
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;
}
//準(zhǔn)備對(duì)象和材質(zhì)球
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;
}
//設(shè)定貼圖
m_uiAtlas.spriteMaterial.mainTexture = tex;
m_uiAtlas.coordinates = UIAtlas.Coordinates.Pixels;
//為對(duì)應(yīng)UISprite接口债蜜,給Atlas加對(duì)象
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);
//設(shè)置完成
m_img.atlas = m_uiAtlas;
m_img.spriteName = tex.name;
}
}
方法2:將整個(gè)UIAtlas及其貼圖打包晴埂,而后形成資源究反,駐留在內(nèi)存中(僅僅是指向資源的指針),UNITY3D會(huì)根據(jù)引用來(lái)確定貼圖是否直接放實(shí)際內(nèi)存中儒洛。這種方法更適合ICON之類有規(guī)律可以配置整合的資源精耐。缺點(diǎn)是需要維護(hù)。
//從資源文件夾加載打包成assetBundle的ICON資源文件
private IEnumerator LoadResIcon()
{
//準(zhǔn)備好資源們
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信息記錄并且綁定成索引晶丘,以便查找
}
}
//根據(jù)ICONNAME找出對(duì)應(yīng)UIATLAS
public UIAtlas FindAtlasBySpriteName(string name)
{
int nAtlasIndex = 0;
if (m_dicIcon.TryGetValue(name, out nAtlasIndex))
{
return m_AtlasData[nAtlasIndex];
}
return null;
}
}
實(shí)際使用的范例:
//設(shè)置顯示對(duì)象
UISprite sprite = this.GetComponent<UISprite>();
sprite.atlas = GameConfig.Instance.IconSet.FindAtlasBySpriteName("Icon001");
sprite.spriteName = "Icon001";
總結(jié):
以上兩種方法基本能夠應(yīng)對(duì)大部分UI的現(xiàn)實(shí)問題黍氮,ImageLoader本身傳入的是Texture2D,所以浅浮,即便是RenderTexture也沒問題,都能與NGUI和諧相處捷枯。加以擴(kuò)展的話滚秩,就是讓另一個(gè)攝像機(jī)導(dǎo)出的東西和當(dāng)前NGUI擺的UI結(jié)合。