目录
一:版本变化
二:为什么使用图集?
二:打包方式
三:如何使用
四:Sprite Packer面板详解
五:打图集的常见问题
六:工具脚本
图集Sprite Packer在 Unity 2020.1以及以后的版本不再作为精灵打包模式的可用选项。以后创建的任何新项目在打包纹理时将默认使用 Sprite Atlas打包图集。
Sprite Atlas讲解:https://blog.csdn.net/HexianWHH/article/details/119520969?spm=1001.2014.3001.5501
1.减少draw call: 多张图片需要多次draw call,合成了一张大图则只需要一次draw call。
创建两个Image使用不同的图片,Batches是2
如果把两个图片打成一个图集,Batches是1
2.减少内存占用:OpenGL ES中每张贴图都需要设置成2的n次方才能使用。比如你有一张宽高为100x100和一张宽高为10x10的图片,如果不合成大贴图,那么需要使用128x128和16x16的两张图片(分别是2的7次方和2的4次方),但如果使用一张大图的话,可以把100x100和10x10的图片放到128x128的大图中,这样就用一张图片。
先来讲解一下旧版unity 图集Sprite Packer的使用说明,使用unity版本2019.4.29f1c1
设置打包方式Editor->Project Settings 下面有Sprite Packer的模式
Disabled:在项目中禁用精灵图集打包。当项目进入播放模式或打包时,不会构建精灵图集。Pack Preview 也禁用。
Enabled for Builds (Legacy Sprite Packer):选择此模式将启用旧版 Sprite Packer 并禁用精灵图集,因为二者无法同时启用。仅针对打包,Unity 使用旧版 Sprite Packer 将精灵进行打包。Editor 和播放模式引用原始源纹理而非打包图集中的纹理。
Always Enabled (Legacy Sprite Packer):选择此模式将启用旧版 Sprite Packer 并禁用精灵图集,因为二者无法同时启用。Unity 使用旧版 Sprite Packer 将所选纹理打包到图集中,且精灵在运行时将引用打包的纹理。但是,精灵将在编辑模式期间引用原始未打包的纹理。
Enabled for Builds:仅针对打包,Unity 将精灵打包到精灵图集中。Editor 和播放模式引用原始源纹理而非精灵图集中的纹理。
Always Enabled:默认情况下会启用此选项。Unity 将所选纹理打包到精灵图集中,且精灵在运行时将引用打包的纹理。但是,精灵将在编辑模式期间引用原始未打包的纹理。
简单理解就是Legacy是旧版本的图集,Enabled For Builds打包是才会启用打图集,Always Enabled 永远启用
public class SpritePackerTool
{
///
/// 图片在Asset下的路径
///
const string ImagePathRoot = "Art/Image";
///
/// 获取所有需要打图集的根文件夹
///
///
static string GetImageRootDir()
{
var imgRootIndex = ImagePathRoot.LastIndexOf("/");
if (imgRootIndex >= 0)
{
return ImagePathRoot.Substring(imgRootIndex + 1);
}
else
{
return ImagePathRoot;
}
}
///
/// 得到图集名称
///
///
///
static string GetPackName(string assetPath)
{
//把\和/路径都统一成/
var newAssetPath = assetPath.Replace("\\", "/");
int imageRootIndex = newAssetPath.IndexOf(ImagePathRoot);
var subImagePath = newAssetPath.Substring(imageRootIndex + ImagePathRoot.Length + 1);
var dirIndex = subImagePath.IndexOf("/");
if (dirIndex < 0)
{
return GetImageRootDir();
}
else
{
return subImagePath.Substring(0, dirIndex);
}
}
///
/// 按照文件夹设置图片的图集名称
///
[MenuItem("SpritePackerTool/SetPackerName")]
static private void SetPackerName()
{
//得到所有图片
var projectRoot = Directory.GetParent(Application.dataPath).FullName;
var imgetFullPath = Path.Combine(Application.dataPath, ImagePathRoot);
int assetPathStartIndex = projectRoot.Length + 1;
var allImagePaths = Directory.GetFiles(imgetFullPath, "*.png", SearchOption.AllDirectories);
foreach (var imagePath in allImagePaths)
{
var assetPath = imagePath.Substring(assetPathStartIndex);
var textureImport = (TextureImporter)AssetImporter.GetAtPath(assetPath);
textureImport.textureType = TextureImporterType.Sprite;
textureImport.spritePackingTag = GetPackName(assetPath);
}
Debug.Log("设置图集名称完成");
}
}
public class ImagePost : AssetPostprocessor
{
///
/// 图片在Asset下的路径
///
const string ImagePathRoot = "Assets/Art/Image";
///
/// 获取所有需要打图集的根文件夹
///
///
static string GetImageRootDir()
{
var imgRootIndex = ImagePathRoot.LastIndexOf("/");
if (imgRootIndex >= 0)
{
return ImagePathRoot.Substring(imgRootIndex + 1);
}
else
{
return ImagePathRoot;
}
}
///
/// 得到图集名称
///
///
///
static string GetPackName(string assetPath)
{
//把\和/路径都统一成/
var newAssetPath = assetPath.Replace("\\", "/");
int imageRootIndex = newAssetPath.IndexOf(ImagePathRoot);
var subImagePath = newAssetPath.Substring(imageRootIndex + ImagePathRoot.Length + 1);
var dirIndex = subImagePath.IndexOf("/");
if (dirIndex < 0)
{
return GetImageRootDir();
}
else
{
return subImagePath.Substring(0, dirIndex);
}
}
//Texture2D导入时执行
void OnPostprocessTexture(Texture2D texture)
{
//不是指定文件夹下面的图片不需要处理
if (!assetPath.StartsWith(ImagePathRoot))
return;
TextureImporter textureImporter = assetImporter as TextureImporter;
textureImporter.textureType = TextureImporterType.Sprite;
textureImporter.spritePackingTag = GetPackName(assetPath);
}
}
public class SpritePackerTool
{
///
/// 图片在Asset下的路径
///
const string ImagePathRoot = "Art/Image";
const string ImagePrefabPathRoot = "Resources/Image/Sprite";
///
/// sprite转换为预制体
///
/// 图片路径
/// 预制体路径
static void ConvertPrefab(string imagePath, string prefabPath)
{
var sprite = AssetDatabase.LoadAssetAtPath(imagePath);
GameObject go = new GameObject(sprite.name);
go.AddComponent().sprite = sprite;
PrefabUtility.SaveAsPrefabAsset(go, prefabPath);
GameObject.DestroyImmediate(go);
}
[MenuItem("SpritePackerTool/MakeSpritePrefab")]
static void MakeSpritePrefab()
{
if (!Directory.Exists(ImagePrefabPathRoot))
{
Directory.CreateDirectory(ImagePrefabPathRoot);
}
var imgetFullPath = Path.Combine(Application.dataPath, ImagePathRoot);
DirectoryInfo imageRootPath = new DirectoryInfo(imgetFullPath);
var allImagePaths = Directory.GetFiles(imgetFullPath, "*.png", SearchOption.AllDirectories);
var projectRoot = Directory.GetParent(Application.dataPath).FullName;
int assetPathStartIndex = projectRoot.Length + 1;
foreach (var imagePath in allImagePaths)
{
var assetPath = imagePath.Substring(assetPathStartIndex);
//把\和/路径都统一成/
var newAssetPath = assetPath.Replace("\\", "/");
int imageRootIndex = newAssetPath.IndexOf(ImagePathRoot);
var subImagePath = newAssetPath.Substring(imageRootIndex + ImagePathRoot.Length + 1);
//检查图片对应的预制体的文件夹存不存在,不存在就创建
var convertPath = Path.Combine(Application.dataPath, ImagePrefabPathRoot, subImagePath);
FileInfo imagePrefab = new FileInfo(convertPath);
if (!imagePrefab.Directory.Exists)
{
Directory.CreateDirectory(imagePrefab.Directory.FullName);
}
var prefabPath = Path.ChangeExtension(Path.Combine("Assets",ImagePrefabPathRoot, subImagePath), ".prefab");
ConvertPrefab(assetPath, prefabPath);
}
}
}
加载图片
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
img.sprite = LoadSprite("Image/Sprite/Image1/Image11/38464da9b7a55b32feaa654fbb4fc5c6");
}
}
private Sprite LoadSprite(string spritePath)
{
return Resources.Load(spritePath).GetComponent().sprite;
}
public class MyPackerPolicy : IPackerPolicy
{
public bool AllowSequentialPacking => true;
///
/// 返回打包程序策略的版本值。如果对策略脚本进行了修改,则该版本应该被触发,并且该策略被保存到版本控制中。
///
///
public int GetVersion()
{
return 1;
}
///
/// 在这里实现你的打包逻辑。定义PackerJob上的地址集,并从给定的TextureImporters中分配Sprites。
///
///
///
///
public void OnGroupAtlases(BuildTarget target, UnityEditor.Sprites.PackerJob job, int[] textureImporterInstanceIDs)
{
}
}