参考文献 :
雨松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:是紧密可旋转打包方式,也就是使用紧密打包,并且允许精灵进行旋转。
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: