ugui图集打包 与资源动态加载

参考文献 : 雨松MOMO UGUI研究院之全面理解图集与使用(三)

启用的方式:在Edit->Project Settings->Editor->Sprite Packer->Mode中进行设置:
1.Disabled:不启用。
2.Enabled For Builds:打包发布时启用。
3.Always Enabled:一直启用,在开发和打包发布阶段都启用,方便开发人员在开发阶段去查看unity自动生成的图集信息,默认推荐使用这种方式。

这里写图片描述
设置tag Ugui图集打包, unity自动会将这些小图按照tag名字打到图集里面去,

查看打包 window->sprite packer

打图集策略 :
1.DefaultPackerPolicy:是默认的打包方式,也是矩形打包方式。他会把所有的小图按照矩形的方式来排列,如果宽高不一样的图片,它们会自动补齐,使用方式就是tag设置时加上”[RECT]图集名”来设置。
2.TightPackerPolicy:是紧密打包方式,也就是尽可能的把图片都打包在图集上,这种方式要比DefaultPackerPolicy打包的图片更多一些,也就是更省空间,使用方式就是tag设置时加上”[TIGHT]图集名”来设置。
3.TightRotateEnabledPackerPolicy:是紧密可旋转打包方式,也就是使用紧密打包,并且允许精灵进行旋转。
注意打包的图片不要放在Rescore下。

到上面图集已经打包完,但如果需要动态加载还需要自己写代码
Atlas 和 AutoSetTextureUISprite 包含using UnityEditor;  需放在 Editor 下否则发布会报错

/// <summary>
/// 导入图片资源到Unity时,自动修改为UI 2D Sprite,自动设置打包tag 为文件夹名字;
/// </summary>
public class AutoSetTextureUISprite : AssetPostprocessor
{
    void OnPostprocessTexture(Texture2D texture)
    {
        //自动设置打包tag;  
        string AtlasName = new DirectoryInfo(Path.GetDirectoryName(assetPath)).Name;
        TextureImporter textureImporter = assetImporter as TextureImporter;
        //自动设置类型;  
        textureImporter.textureType = TextureImporterType.Sprite;
        textureImporter.spritePackingTag = AtlasName;
        textureImporter.mipmapEnabled = false;
    }
}

我是按照文件加打包图集的,
制作思路:将Atlas每个文件夹 对应生成一个预制,再在预制下对应文件夹图片生成对应的sprite,我这时用Image 存储sprite的,
有更好的可以使用其他存储,所有sprite生成完后将预制保存在Resourses/Texture2D 下

using UnityEngine;
using UnityEditor;
using System.IO;

 /// <summary>
 ///1.遍历“Atlas”下的每个文件夹,。 
 ///2.创建一个go,添加AtlasMap脚本,把文件夹下所有的Sprite都添加到go上, 
 /// 3.将go创建为对应预设,并放置到“Resources/Texture2D”下的对应文件夹处,预设名字为“文件夹名”,然后将go删除。
 /// </summary>
public class Atlas
{
    [MenuItem("Edit Tools/ AtlasMaker")]
    public static void MakeAtlas()
    {
        string targetDir = Application.dataPath + "/Atlas";
        if (!Directory.Exists(targetDir))
        {
            Directory.CreateDirectory(targetDir);
        }
        DirectoryInfo fromDirInfo = new DirectoryInfo(targetDir);
        foreach (DirectoryInfo dirInfo in fromDirInfo.GetDirectories())
        {
            MakeOnePrefab(dirInfo, fromDirInfo);
            //if (dirInfo.Name == "MainUI")
            //// 因为MainUI下面还有很多子级别,子级别也有对应的动态图集列表// 
            //{
            //    foreach (DirectoryInfo mainUIChildDir in dirInfo.GetDirectories())
            //    {
            //        MakeOnePrefab(mainUIChildDir, fromDirInfo, targetDir + "/MainUI");
            //    }
            //}
            //else
            //{
            //    MakeOnePrefab(dirInfo, fromDirInfo, targetDir);
            //}
        }
    }

    /// <summary>
    /// 遍历文件夹下所有图片进行节点生成
    /// </summary>
    /// <param name="dirInfo">文件夹</param>
    /// <param name="fromDirInfo">起始文件夹</param>
    static void MakeOnePrefab(DirectoryInfo dirInfo, DirectoryInfo fromDirInfo)
    {
        string fieldName = dirInfo.Name;
        FileInfo[] allPngFiles = null;
        //找到所有.png文件
        allPngFiles = dirInfo.GetFiles("*.png", SearchOption.AllDirectories);

        if (allPngFiles.Length <= 0)
        {
            string shortPath = fromDirInfo.FullName.Substring(fromDirInfo.FullName.IndexOf("Assets"));
            Debug.LogWarning(string.Format("There is no sprite where path is {0}/{1}.Do you forget to add needed sprite there?", shortPath, fieldName));
        }
        else
        {
            GameObject gameObject = new GameObject(fieldName);
            AtlasMap atlasMap = gameObject.AddComponent<AtlasMap>();
            // 如果“Resources/UI”下没有和“ResourcesHW/UI对应的文件夹”则创建一个
            // 
            string prefabParentFieldPath = string.Format(Application.dataPath + "/Resources/Texture2D");
            if (!Directory.Exists(prefabParentFieldPath))
            {
                Directory.CreateDirectory(prefabParentFieldPath);
            }

            // 将Sprite存入AtlasMap脚本中
            foreach (FileInfo pngFile in allPngFiles)
            {
                string assetPath = pngFile.FullName.Substring(pngFile.FullName.IndexOf("Assets"));
                Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>(assetPath);
                if (sprite == null)
                {
                    Debug.LogWarning(string.Format("It’s not a sprite which path is {0}, and don’t move it to DynSprite field.", assetPath));
                    continue;
                }
                atlasMap.AddSprite(sprite);
            }
            // 在对应文件夹上生成预设
            string prefabAllPath = string.Format("{0}/{1}.prefab", prefabParentFieldPath, fieldName);
            string prefabPath = prefabAllPath.Substring(prefabAllPath.IndexOf("Assets"));
            PrefabUtility.CreatePrefab(prefabPath, gameObject);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
            // 销毁go// 
            GameObject.DestroyImmediate(gameObject);
        }
    }
}


using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 用于存储制作好的动态图预设上的sprite信息
/// </summary>
public class AtlasMap : MonoBehaviour
{
    public Sprite GetSpriteByName(string name)
    {
        if (transform.Find(name))
        {
            return transform.Find(name).GetComponent<SpriteRenderer>().sprite;
        }
        return null;
    }
    public void AddSprite(Sprite sp)
    {
        GameObject gameObject = new GameObject();
        gameObject.name = sp.name;
        SpriteRenderer image =gameObject.AddComponent<SpriteRenderer>();
        image.sprite = sp;
        gameObject.transform.SetParent(transform);
    }
}
最后使用时先Edit Tools -- >AtlasMaker 下,就能生成了对应预制
查找sprite
    /// <summary>
    /// 根据文件和路径名,找到对应sprite,
    /// 注意使用时先Edit Tools -- AtlasMaker 下会在Resources/Texture2D下生成对应动态加载预制
    /// </summary>
    /// <param name="type">对应存放节点的预制</param>
    /// <param name="spriteName"> 名字</param>
    /// <returns>返回搜索到的精灵</returns>
    public static Sprite GetSpriteByTypeAndName(string prefab, string spriteName)
    {
        GameObject go = Resources.Load(prefab) as GameObject;
        if (go == null)
        {
            Debug.LogError(string.Format("There is no prefab of {0}. Be sure that type is right and you had make atlas of type", prefab));
            return null;
        }
        AtlasMap am = go.GetComponent<AtlasMap>();
        if (am == null)
        {
            Debug.LogError(string.Format("There is no AtlasMap on prefab of {0}.Be sure MakeAtlasMaker work", prefab));
            return null;
        }
        return am.GetSpriteByName(spriteName);
    }
}
效果图
用了几天发现,每次导图集的引用都会全部导一遍,耗时慢,而且多人开发的化容易出现冲突,所以对操作进行修改了下

将Atlas 修改了下

using UnityEngine;
using UnityEditor;
using System.IO;
using System.Collections.Generic;

/// <summary>
///1.遍历“Atlas”下的每个文件夹,。 
///2.创建一个go,添加AtlasMap脚本,把文件夹下所有的Sprite都添加到go上, 
/// 3.将go创建为对应预设,并放置到“Resources/Texture2D”下的对应文件夹处,预设名字为“文件夹名”,然后将go删除。
/// </summary>
public class Atlas
{
    [MenuItem("Assets/导出图集引用")]
    public static void MakeAtlas()
    {
        Object[] objects = Selection.GetFiltered(typeof(object), SelectionMode.Assets);
        List<string> directoryName = GetDirectoryName(objects);

        for (int i = 0; i < directoryName.Count; i++)
        {
            string targetDir = Application.dataPath + "/Atlas/"+ directoryName[i];
            if (!Directory.Exists(targetDir))
            {
                //选错文件夹跳过
                continue;
            }
            DirectoryInfo fromDirInfo = new DirectoryInfo(targetDir);
            MakeOnePrefab(fromDirInfo, fromDirInfo);
            //if (dirInfo.Name == "MainUI")
            //// 因为MainUI下面还有很多子级别,子级别也有对应的动态图集列表// 
            //{
            //    foreach (DirectoryInfo mainUIChildDir in dirInfo.GetDirectories())
            //    {
            //        MakeOnePrefab(mainUIChildDir, fromDirInfo, targetDir + "/MainUI");
            //    }
            //}
            //else
            //{
            //    MakeOnePrefab(dirInfo, fromDirInfo, targetDir);
            //}
        }
    }

    /// <summary>
    /// 遍历文件夹下所有图片进行节点生成
    /// </summary>
    /// <param name="dirInfo">文件夹</param>
    /// <param name="fromDirInfo">起始文件夹</param>
    static void MakeOnePrefab(DirectoryInfo dirInfo, DirectoryInfo fromDirInfo)
    {
        string fieldName = dirInfo.Name;
        FileInfo[] allPngFiles = null;
        //找到所有.png文件
        allPngFiles = dirInfo.GetFiles("*.png", SearchOption.AllDirectories);

        if (allPngFiles.Length <= 0)
        {
            string shortPath = fromDirInfo.FullName.Substring(fromDirInfo.FullName.IndexOf("Assets"));
            Debug.LogWarning(string.Format("There is no sprite where path is {0}/{1}.Do you forget to add needed sprite there?", shortPath, fieldName));
        }
        else
        {
            GameObject gameObject = new GameObject(fieldName);
            AtlasMap atlasMap = gameObject.AddComponent<AtlasMap>();
            // 如果“Resources/UI”下没有和“ResourcesHW/UI对应的文件夹”则创建一个
            // 
            string prefabParentFieldPath = string.Format(Application.dataPath + "/Resources/Texture2D");
            if (!Directory.Exists(prefabParentFieldPath))
            {
                Directory.CreateDirectory(prefabParentFieldPath);
            }

            // 将Sprite存入AtlasMap脚本中
            foreach (FileInfo pngFile in allPngFiles)
            {
                string assetPath = pngFile.FullName.Substring(pngFile.FullName.IndexOf("Assets"));
                Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>(assetPath);
                if (sprite == null)
                {
                    Debug.LogWarning(string.Format("It’s not a sprite which path is {0}, and don’t move it to DynSprite field.", assetPath));
                    continue;
                }
                atlasMap.AddSprite(sprite);
            }
            // 在对应文件夹上生成预设
            string prefabAllPath = string.Format("{0}/{1}.prefab", prefabParentFieldPath, fieldName);
            string prefabPath = prefabAllPath.Substring(prefabAllPath.IndexOf("Assets"));
            PrefabUtility.CreatePrefab(prefabPath, gameObject);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
            Debug.Log(fieldName+ ".prefab 生成成功" );
            // 销毁go// 
            GameObject.DestroyImmediate(gameObject);

        }
    }

    /// <summary>
    /// 获取所选文件夹的名字
    /// </summary>
    /// <param name="objects"></param>
    /// <returns></returns>
    static List<string> GetDirectoryName(Object[] objects)
    {
        Dictionary<string, bool> directoryName = new Dictionary<string, bool>();

        for (int i = 0; i < objects.Length; i++)
        {
            string direcName = AssetDatabase.GetAssetPath(objects[i]);
            string curDirectoryName = new DirectoryInfo(direcName).Name;
            if (!directoryName.ContainsKey(curDirectoryName))
            {
                Debug.Log("文件夹名=" + curDirectoryName);
            }
            directoryName[curDirectoryName] = true;
        }
        List<string> vs = new List<string>(directoryName.Keys);
        return vs;
    }
}


操作改为,选中你要导出的图集的文件夹-》右键

demo 我就不更新了,将代码替换掉就行


demo:

猜你喜欢

转载自blog.csdn.net/weixin_41843959/article/details/80411529