NGUI提供了很方便的UIAtlas,其主要作用是改进DrawCall,把众多图片整合在一张贴图上,由于简单易用的好处,所以只是用原生的GUI很容易忽视DrawCall的
问题
,所以NGUI为了改进,才有了UIAtlas。当然NGUI还做了很多优化。
这里主要还是介绍如何利用UISprite来动态的加载图片。NGUI所提供的UIAtlas虽然好用,但只能在Editor内生成贴图和prefab以供UISprite使用。为了能够让游戏资源与游戏本体尽可能的分离,特别是游戏资源需要动态更新的情况。很多时候,都需要动态加载,动态设置UIAtlas。
这里主要介绍2个方法。
方法1:直接在代码中创建和设置UIAtlas并对UISprite进行显示。这种方法可以对任何零散的贴图进行加载,但缺点是浪费DrawCall,主要应用在特别零散的贴图资源上。
方法2:将整个UIAtlas及其贴图打包,而后形成资源,驻留在内存中(仅仅是指向资源的指针),UNITY3D会根据引用来确定贴图是否直接放实际内存中。这种方法更适合ICON之类有规律可以配置整合的资源。缺点是需要维护。
管理UIAtlas
总结:
以上两种方法基本能够应对大部分UI的现实问题,ImageLoader本身传入的是Texture2D,所以,即便是RenderTexture也没问题,都能与NGUI和谐相处。加以扩展的话,就是让另一个摄像机导出的东西和当前NGUI摆的UI结合。
这里主要还是介绍如何利用UISprite来动态的加载图片。NGUI所提供的UIAtlas虽然好用,但只能在Editor内生成贴图和prefab以供UISprite使用。为了能够让游戏资源与游戏本体尽可能的分离,特别是游戏资源需要动态更新的情况。很多时候,都需要动态加载,动态设置UIAtlas。
这里主要介绍2个方法。
方法1:直接在代码中创建和设置UIAtlas并对UISprite进行显示。这种方法可以对任何零散的贴图进行加载,但缺点是浪费DrawCall,主要应用在特别零散的贴图资源上。
[AppleScript]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
public
class
ImageLoader
:
MonoBehaviour
{
/
/
需要加载动态图片的对象
public UISprite m_img;
/
/
自用的Atlas
private UIAtlas m_uiAtlas;
/
/
/
<s
ummary
>
/
/
/
加载的贴图
/
/
/
<
/
summary
>
/
/
/
<
param
name
=
“tex”
>
Tex.
<
/
param
>
public void ImageLoad
(
Texture
2
D 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
(
0
f
,
0
f
,
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之类有规律可以配置整合的资源。缺点是需要维护。
[AppleScript]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
/
/
从资源文件夹加载打包成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
[AppleScript]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
public
class
IconSet
{
public
string
[] strIcons
=
{
“A
1
_Atlas”
,
“A
2
_Atlas”
,
“A
3
_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
(
“Icon
001
”
)
;
sprite.spriteName
=
“Icon
001
”;
|
总结:
以上两种方法基本能够应对大部分UI的现实问题,ImageLoader本身传入的是Texture2D,所以,即便是RenderTexture也没问题,都能与NGUI和谐相处。加以扩展的话,就是让另一个摄像机导出的东西和当前NGUI摆的UI结合。