NGUI Atlas整理工具

发表于2017-03-15
评论2 3.4k浏览

  NGUI Atlas整理工具的出现是为了解决使用NGUI的Atlas时,不好去整理Atlas的问题,美术同学在开始制作时,很难完美地规划一个Sprite放在那个Atlas里,后期由于DrawCall,内存等优化需求,很可能需要把一个Sprite从一个Atlas移动到另一个,但这个时候一个尴尬的问题出现了: 已经做好的Prefab怎么办?手工调整的话,面临着工作量过大的问题,而且,很难保证不出错。于是,一个靠谱的Atlas整理工具的需求就出现了。

界面

分左右两边,每边显示一个Atlas

功能
  自动查找到使用AtlasPrefab
  自动查找到没有被使用的Sprite, 并使用红色字体标示出来
  左边移动到右边,右边移动到左边,并在移动时,自动修改使用AtlasPrefab
  支持删除没有被使用的Sprite,如果有被使用,会提示用户

实现
  实现还是很简单的,一个依赖查找器,和一个界面绘制类即可

1
2
3
4
5
6
7
8
9
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
43
44
45
46
public class AtlasAssetScan : ObjectSingleton
{
    string[] PREFAB_DIRS = new string[] { "Assets/Resources/UI/Prefab/", "Assets/ArtSource/UI/Prefab/" };
 
    public List FindDepend(UIAtlas atlas)
    {
        var results = new List();
 
        string atlasPath = AssetDatabase.GetAssetPath(atlas.GetInstanceID());
 
        var list = AssetDatabase.GetAllAssetPaths();
 
        foreach(var path in list)
        {
            if (!PREFAB_DIRS.Any((dir)=>{return path.StartsWith(dir);}))
            {
                continue;
            }
 
            var prefab = AssetDatabase.LoadMainAssetAtPath(path) as GameObject;
 
            if (prefab == null)
            {
                continue;
            }
 
            var deps = AssetDatabase.GetDependencies(path, true);
            if (!deps.Contains(atlasPath))
            {
                continue;
            }
 
            results.Add(prefab);
        }
 
        return results;
    }
 
    public List<string> FindUnusedSprites(UIAtlas atlas)
    {
    }
 
    public List FindDepend(UIAtlas atlas, string spriteName)
    {
    }
}string>

  扫描指定目录,使用AssetDatabase的接口,获取以来关系即可
  界面绘制方面,基于Unity编辑器强大的LayoutDraw功能还是比较容易实现的
  UI分割,使用了EditorGUILayoutHorizontalPanes外部组件

1
2
3
4
5
6
7
8
9
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
43
44
45
46
47
public static void SwitchSprite(bool left, UISpriteData sd)
{
    UIAtlas source = null;
    UIAtlas target = null;
    if (left)
    {
        source = instance.leftAtlas.atlas;
        target = instance.rightAtlas.atlas;
    }
    else
    {
        source = instance.rightAtlas.atlas;
        target = instance.leftAtlas.atlas;
    }
 
    SwitchSprite(source, target, sd);
}
 
static void SwitchSprite(UIAtlas source, UIAtlas target, UISpriteData sd)
{
    if (target.GetSprite(sd.name) != null)
    {
        EditorUtility.DisplayDialog("Error To Move", string.Format("不能移动 Sprite {0} 在目标atlas {1} 中有同名Sprite", sd.name, target), "OK");
        return;
    }
 
    UIAtlasMaker.SpriteEntry entry = null;
    List sprites = new List();
    UIAtlasMaker.ExtractSprites(source, sprites);
    for (int i = sprites.Count; i > 0;)
    {
        UIAtlasMaker.SpriteEntry ent = sprites[--i];
        if (ent.name == sd.name)
        {
            entry = ent;
            sprites.RemoveAt(i);
        }
    }
    UIAtlasMaker.UpdateAtlas(source, sprites);
 
    sprites.Clear();
    UIAtlasMaker.ExtractSprites(target, sprites);
    sprites.Add(entry);
    UIAtlasMaker.UpdateAtlas(target, sprites);
 
    ModifyPrefab(source, target, sd.name);
}

Sprite交换,使用NGUI自带的UIAtlasMaker即可

总结
  虽然只是一个小工具,但也可以大大提升工作效率,提高美术同学的幸福感
  在UGUI虽然UnityAtlas的打包过程屏蔽了起来,为我们带来了便利。但很多项目为了效率,和便于控制最终Atlas,以及AssetBundle打包等原因还是会自己拼Atlas,希望这个NGUIAtlas整理工具可以给大家带来一些启发

 

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引