UI目录
目录结构.png
两个自定义类
#if UNITY_EDITOR
//Debug.Log(Regex.IsMatch(path, "Assets/UI/Modules/.[a-zA-Z0-9]*/Images/.[a-zA-Z0-9]*/.[^/]*.png"));
//Debug.Log(Regex.IsMatch(path, "Assets/UI/Modules/.[^/]*/Images/.[^/]*/.[^/]*.png"));
/// <summary>
/// 图片路径
/// </summary>
public class SpriteTemp
{
/// <summary>
/// 图片是不是UI模块
/// </summary>
public bool isUI;
/// <summary>
/// 图片所在模块
/// </summary>
public string moduleName;
/// <summary>
/// 图片父路径
/// </summary>
public string parentPath;
/// <summary>
/// 图片所在的图集名
/// </summary>
public string atlasName;
public SpriteTemp(string path)
{
path = path.Replace("\\", "/");
string[] pathSplit = path.Split('/');
if (pathSplit.Length == 7)
{
if (pathSplit[1].Equals("UI") && pathSplit[2].Equals("Modules") && pathSplit[4].Equals("Images") && pathSplit[6].Contains(".png"))
{
this.isUI = true;
this.moduleName = pathSplit[3];
this.parentPath = $"Assets/UI/Modules/{this.moduleName}/Images/{pathSplit[5]}";
this.atlasName = $"Atlas_{this.moduleName}_{pathSplit[5]}.spriteatlas";
return;
}
}
this.isUI = false;
}
}
/// <summary>
/// 一个路径是不是UIAtlas路径
/// </summary>
public class AtlasTemp
{
public bool isAtlas;
/// <summary>
/// 图集所在模块名
/// </summary>
public string moduleName;
/// <summary>
/// 图集的父文件路径
/// </summary>
public string parentPath;
/// <summary>
/// 图集的名字
/// </summary>
public string atlasName;
public AtlasTemp(string path)
{
string[] pathSplit = path.Split('/');
if (pathSplit.Length == 6)
{
if (pathSplit[1].Equals("UI") && pathSplit[2].Equals("Modules") && pathSplit[4].Equals("Images"))
{
this.isAtlas = true;
this.moduleName = pathSplit[3];
this.parentPath = $"Assets/UI/Modules/{this.moduleName}/Images/{pathSplit[5]}";
this.atlasName = $"Atlas_{this.moduleName}_{pathSplit[5]}.spriteatlas";
return;
}
}
this.isAtlas = false;
}
}
#endif
监听资源导入
using UnityEngine;
using UnityEditor;
public class AssetImportEditor : AssetPostprocessor
{
//这里要重新整理,把删除、移动、添加的方法拆分开
public static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssets)
{
//Debug.Log("OnPostprocessAllAssets");
foreach (string assetPath in importedAssets)
{
Debug.Log("导入资源 : " + assetPath);
}
ImportSpriteEditor.DeletedSprite(deletedAssets);
ImportSpriteEditor.MoveSprite(movedAssets, movedFromAssets);
}
//--导入贴图前
public void OnPreprocessTexture()
{
Debug.Log("导入贴图前 OnPreprocessTexture");
ImportSpriteEditor.TextureToSprite(assetPath, assetImporter);
}
//--导入精灵后
public void OnPostprocessSprites(Texture2D texture, Sprite[] sprites)
{
Debug.Log("导入精灵后 " + assetPath);
AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceSynchronousImport);
ImportSpriteEditor.AddSprites(assetPath, texture);
}
//--导入贴图后
public void OnPostprocessTexture(Texture2D texture2D)
{
//Debug.Log("导入贴图后 OnPostprecessTexture");
}
public void OnPreprocessAudio()
{
Debug.Log("导入声音前 OnPreprocessAudio");
AudioImporter audioImporter = (AudioImporter)assetImporter;
Debug.Log(string.Format("路径 :{0}", audioImporter.assetPath));
}
//--导入声音后
public void OnPostprocessAudio(AudioClip clip)
{
Debug.Log("导入声音后 OnPostprocessAudio");
}
//--导入模型前
public void OnPreprocessModel()
{
Debug.Log("导入模型前 OnPreprocessModel");
ModelImporter modelImporter = (ModelImporter)assetImporter;
}
//--导入模型后
public void OnPostprocessModel(GameObject gameObject)
{
Debug.Log("导入模型后 OnPostprocessModel");
}
//--导入动画前
public void OnPreprocessAnimation()
{
Debug.Log("导入动画前 OnPreprocessAnimation");
ModelImporter modelImporter = (ModelImporter)assetImporter;
}
//--导入动画后
public void OnPostprocessAnimation(GameObject gameObject, AnimationClip animationClip)
{
Debug.Log("导入动画后 OnPostprocessAnimation");
}
//--导入材质后
public void OnPostprocessMaterial(Material material)
{
Debug.Log("导入材质后 OnPostprocessMaterial");
}
}
检查是否是UGUI模块
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class ImportSpriteEditor : Editor
{
static SpriteTemp add_sprite_temp = null;
static Dictionary<string, SpriteTemp> deleted_sprite_refresh = new Dictionary<string, SpriteTemp>();
static Dictionary<string, SpriteTemp> move_sprite_refresh = new Dictionary<string, SpriteTemp>();
public static void TextureToSprite(string assetPath, AssetImporter assetImporter)
{
SpriteTemp spriteTemp = new SpriteTemp(assetPath);
if (spriteTemp.isUI)
{
//是UI模块
TextureImporter textureImporter = (TextureImporter)assetImporter;
textureImporter.alphaSource = TextureImporterAlphaSource.FromInput;
textureImporter.alphaIsTransparency = true;
textureImporter.isReadable = false;
textureImporter.textureCompression = TextureImporterCompression.Uncompressed;
textureImporter.textureType = TextureImporterType.Sprite;
//textureImporter.spritePackingTag = $"UIAtlas_{atlasData.moduleName}_{atlasData.fileName}";
textureImporter.SaveAndReimport();
TextureImporterPlatformSettings platformSetting = new TextureImporterPlatformSettings()
{
maxTextureSize = 1024,
resizeAlgorithm = TextureResizeAlgorithm.Bilinear,
format = TextureImporterFormat.Automatic,
textureCompression = TextureImporterCompression.Compressed,
crunchedCompression = false
};
textureImporter.SetPlatformTextureSettings(platformSetting);
}
}
public static void AddSprites(string assetPath, Texture2D texture)
{
add_sprite_temp = null;
SpriteTemp spriteTemp = new SpriteTemp(assetPath);
if (spriteTemp.isUI)
{
Debug.Log($"添加UI : {assetPath}");
add_sprite_temp = spriteTemp;
//int value1 = texture.width % 4;
//int value2 = texture.height % 4;
//if (value1 != 0 || value2 != 0)
//{
// Debug.LogError($"图片不符合规范,纹理的长宽都是4的倍数,才能被压缩成DXT5格式,图片位置:{assetPath}");
//}
}
EditorApplication.delayCall += onDelayCalls_Add;
}
static void onDelayCalls_Add()
{
if (add_sprite_temp != null)
{
AtlasEditor.RefreshSpriteAtlas(add_sprite_temp.parentPath, add_sprite_temp.atlasName);
}
EditorApplication.delayCall -= onDelayCalls_Add;
}
public static void DeletedSprite(string[] assetPaths)
{
if (assetPaths.Length <= 0) return;
deleted_sprite_refresh.Clear();
for (int i = 0; i < assetPaths.Length; i++)
{
SpriteTemp spriteTemp = new SpriteTemp(assetPaths[i]);
if (spriteTemp.isUI && deleted_sprite_refresh.ContainsKey(spriteTemp.parentPath) == false)
{
deleted_sprite_refresh.Add(spriteTemp.parentPath, spriteTemp);
}
}
EditorApplication.delayCall += onDelayCalls_Deleted;
}
static void onDelayCalls_Deleted()
{
foreach (var item in deleted_sprite_refresh)
{
SpriteTemp spriteTemp = item.Value;
AtlasEditor.RefreshSpriteAtlas(spriteTemp.parentPath, spriteTemp.atlasName);
}
EditorApplication.delayCall -= onDelayCalls_Deleted;
}
public static void MoveSprite(string[] movedAssets, string[] movedFromAssets)
{
if (movedAssets.Length <= 0) return;
move_sprite_refresh.Clear();
for (int i = 0; i < movedAssets.Length; i++)
{
string newPath = movedAssets[i];
string oldPath = movedFromAssets[i];
//刷新 oldPath Atlas
SpriteTemp old_spriteTemp = new SpriteTemp(oldPath);
if (old_spriteTemp.isUI && move_sprite_refresh.ContainsKey(old_spriteTemp.parentPath) == false)
{
move_sprite_refresh.Add(old_spriteTemp.parentPath, old_spriteTemp);
}
//刷新 newPath Atlas
SpriteTemp new_spriteTemp = new SpriteTemp(newPath);
if (new_spriteTemp.isUI && move_sprite_refresh.ContainsKey(new_spriteTemp.parentPath) == false)
{
move_sprite_refresh.Add(new_spriteTemp.parentPath, new_spriteTemp);
}
}
EditorApplication.delayCall += onDelayCalls_Move;
}
static void onDelayCalls_Move()
{
foreach (var item in move_sprite_refresh)
{
SpriteTemp spriteTemp = item.Value;
AtlasEditor.RefreshSpriteAtlas(spriteTemp.parentPath, spriteTemp.atlasName);
}
EditorApplication.delayCall -= onDelayCalls_Move;
}
}
创建图集
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEditor;
using UnityEditor.U2D;
using UnityEngine;
using UnityEngine.U2D;
public class AtlasEditor : Editor
{
[MenuItem("Tools/刷新(创建)图集")]
public static void onCreateAtlas()
{
string rootPath = Path.Combine(Application.dataPath, "UI/Modules");
//获取文件夹下的一级子文件夹
string[] allModule = Directory.GetDirectories(rootPath);
foreach (string modulePath in allModule)
{
//模块下是否存在方图片的文件夹
//Images下不允许直接方图片,需要放在Images的子文件夹中,如:Images/Common,Images/bg 等
string imagesDire = Path.Combine(modulePath, "Images");
bool isExists = Directory.Exists(imagesDire);
if (isExists)
{
string[] allImagesDire = Directory.GetDirectories(imagesDire);
foreach (string imageDire in allImagesDire)
{
string direPath = "Assets" + imageDire.Substring(Application.dataPath.Length);
direPath = direPath.Replace("\\", "/");
AtlasTemp atlasTemp = new AtlasTemp(direPath);
if (atlasTemp.isAtlas)
{
RefreshSpriteAtlas(atlasTemp.parentPath, atlasTemp.atlasName);
}
}
}
}
}
public static void RefreshSpriteAtlas(string parentPath, string atlasName)
{
Debug.Log("RefreshSpriteAtlas " + parentPath);
string atlasPath = $"{parentPath}/{atlasName}";
_ClearSpriteAtlas(parentPath, atlasName);
SpriteAtlas atlas = AssetDatabase.LoadAssetAtPath<SpriteAtlas>(atlasPath);
string[] spritePathArr = Directory.GetFiles(parentPath, "*.png");
if (spritePathArr.Length <= 0)
{
if (atlas != null)
{
AssetDatabase.DeleteAsset(atlasPath);
}
return;
}
if (atlas == null)
{
_isCreateSpriteAtlas(atlasPath, spritePathArr);
}
else
{
_isRefreshSpriteAtlas(atlas, spritePathArr);
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
static void _isRefreshSpriteAtlas(SpriteAtlas atlas, string[] spritePathArr)
{
Dictionary<string, Sprite> keyValues = new Dictionary<string, Sprite>();
for (int i = 0; i < spritePathArr.Length; i++)
{
string spritePath = spritePathArr[i].Replace("\\", "/");
Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>(spritePath);
if (sprite != null)
{
string spriteName = Path.GetFileNameWithoutExtension(spritePath);
keyValues.Add(spriteName, sprite);
}
}
var spriteArr = SpriteAtlasExtensions.GetPackables(atlas);
var SpriteAtlasExtensions_Type = typeof(SpriteAtlasExtensions);
var RemoveAt = SpriteAtlasExtensions_Type.GetMethod("RemoveAt", BindingFlags.Static | BindingFlags.NonPublic);
for (int i = spriteArr.Length - 1; i >= 0; i--)
{
if (spriteArr[i] == null)
{
RemoveAt.Invoke(null, new[] { atlas, (object)i });
}
else
{
string name = spriteArr[i].name;
if (keyValues.ContainsKey(name))
{
keyValues.Remove(name);
}
else
{
RemoveAt.Invoke(null, new[] { atlas, (object)i });
}
}
}
/*
SerializedObject serializedObject = new SerializedObject(atlas);
SerializedProperty packables = serializedObject.FindProperty("m_EditorData.packables");
for (int i = packables.arraySize - 1; i >= 0; i--)
{
SerializedProperty texsp = packables.GetArrayElementAtIndex(i);
string spritePath = texsp.objectReferenceValue != null ? AssetDatabase.GetAssetPath(texsp.objectReferenceValue) : string.Empty;
//string spriteParent = string.IsNullOrEmpty(spritePath) ? string.Empty : Path.GetDirectoryName(spritePath).Replace("\\", "/");
//if (string.IsNullOrEmpty(spriteParent) || spriteParent != atlasTemp.parentPath || keyValuePairs.ContainsKey(spritePath) == false)
//{
// texsp.objectReferenceValue = null;
// packables.DeleteArrayElementAtIndex(i);
//}
if (!string.IsNullOrEmpty(spritePath) && keyValues.ContainsKey(spritePath))
{
keyValues.Remove(spritePath);
}
else
{
texsp.objectReferenceValue = null;
packables.DeleteArrayElementAtIndex(i);
}
}
serializedObject.ApplyModifiedProperties();
*/
List<Sprite> spriteList = new List<Sprite>();
foreach (var item in keyValues)
{
spriteList.Add(item.Value);
}
atlas.Add(spriteList.ToArray());
}
static void _isCreateSpriteAtlas(string atlasPath, string[] spritePathArr)
{
SpriteAtlas atlas = _CreateSpriteAtlas(atlasPath);
List<Sprite> sprites = new List<Sprite>();
for (int i = 0; i < spritePathArr.Length; i++)
{
string spritePath = spritePathArr[i].Replace("\\", "/");
Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>(spritePath);
if (sprite != null)
{
sprites.Add(sprite);
}
}
atlas.Add(sprites.ToArray());
/*
//SerializedObject serializedObject = new SerializedObject(atlas);
//SerializedProperty packables = serializedObject.FindProperty("m_EditorData.packables");
//for (int i = 0; i < sprites.Count; i++)
//{
// packables.InsertArrayElementAtIndex(i);
// packables.GetArrayElementAtIndex(i).objectReferenceValue = sprites[i];
//}
//serializedObject.ApplyModifiedProperties();
*/
}
static void _ClearSpriteAtlas(string parentPath, string atlasName)
{
string[] allAtlas = Directory.GetFiles(parentPath, "*.spriteatlas");
foreach (string atlasPath in allAtlas)
{
//获取此文件夹下所有图集并删除不符合规范的图集
string name = Path.GetFileName(atlasPath);
if (atlasName.Equals(name) == false)
{
//删除不符合命名规范的图集
AssetDatabase.DeleteAsset(atlasPath);
}
}
}
/// <summary>
/// 创建一个图集
/// </summary>
/// <param name="atlasPath"></param>
/// <returns></returns>
static SpriteAtlas _CreateSpriteAtlas(string atlasPath)
{
SpriteAtlas atlas = new SpriteAtlas();
//此选项为false时,需要手写atlas加载方法:SpriteAtlasManager.atlasRequested += void
atlas.SetIncludeInBuild(true);
SpriteAtlasPackingSettings packSetting = new SpriteAtlasPackingSettings()
{
blockOffset = 1,
enableRotation = false,
enableTightPacking = false,
padding = 4,
};
atlas.SetPackingSettings(packSetting);
SpriteAtlasTextureSettings textureSetting = new SpriteAtlasTextureSettings()
{
readable = false,
generateMipMaps = false,
sRGB = true,
filterMode = FilterMode.Bilinear,
};
atlas.SetTextureSettings(textureSetting);
AssetDatabase.CreateAsset(atlas, atlasPath);
return atlas;
}
}