本文主要是介绍Unity - 模拟Sprite Packer合并多个Sprite,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Unity - 模拟Sprite Packer合并多个Sprite
现在做一个卡牌Demo,由于没有沟通好,动画师为了做Anima2D动画方便,把角色每个部位拆分成单个Sprite,这样肯定是不行的,不仅加大了容量,运行时效率也不高。但是由于动画已经做好了,再回去手动合并再修改Anima2D非常麻烦,只好让程序实现一个快捷工具,把单个的Sprite合成一张大图集,把与单个Sprite绑定的Anima2D数据迁移到大图集。忙了一天总算弄好了,现在记录一下。
Sprite Packer
把Sprite合并成图集其实是Unity内置的功能——Sprite Packer,Sprite Packer会把相同Packing Tag的Sprite合并成大图集,我们要做的就是模拟Sprite Packer。简单的一个思路是:把要打包的Sprite放到一个文件下;得到所有单独的Sprite;生成单独的Texture;打包;切分Texture。
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using System.Linq;namespace Utility
{public class AtlasTest{[UnityEditor.MenuItem("SpriteAtlas/CreateAtlas")]public static void CreateAtlas(){string spritePath = string.Empty;spritePath = EditorUtility.OpenFolderPanel("选择文件夹", "", "");List<Sprite> sprites = new List<Sprite>();List<Texture2D> newTexs = new List<Texture2D>();List<string> extensions = new List<string>() { ".png", ".jpg", ".psd" };// 找出单独的spritestring[] files = Directory.GetFiles(spritePath, "*.*", SearchOption.AllDirectories).Where(s => extensions.Contains(Path.GetExtension(s).ToLower())).ToArray();for (int i = 0; i < files.Length; i++){string relativePath = files[i].Substring(files[i].IndexOf("Asset")).Replace('\\', '/');Object[] newSprites = AssetDatabase.LoadAllAssetsAtPath(relativePath);for (int j = 0; j < newSprites.Length; j++){if ((newSprites[j] as Sprite) != null)sprites.Add(newSprites[j] as Sprite);}}// 把单独的sprite变化成texturefor (int i = 0; i < sprites.Count; i++){Rect t_Rect = sprites[i].rect;Texture2D t_SourceTex = sprites[i].texture;string pathStr = AssetDatabase.GetAssetPath(sprites[i].texture);// 开启源Spirte的可读TextureImporter t_Importer = AssetImporter.GetAtPath(pathStr) as TextureImporter;t_Importer.isReadable = true;t_Importer.SaveAndReimport();AssetDatabase.ImportAsset(pathStr);// 裁剪出新的TextureColor[] t_Colors = t_SourceTex.GetPixels((int)t_Rect.x, (int)t_Rect.y, (int)t_Rect.width, (int)t_Rect.height);newTexs.Add(new Texture2D((int)t_Rect.width, (int)t_Rect.height));newTexs[i].SetPixels(t_Colors);}// 打包成Atlasstring atlasPath = spritePath + "/AllAtlas.png";string atlasRelativePath = atlasPath.Substring(atlasPath.IndexOf("Assets"));Texture2D atlasTex = new Texture2D(1024, 1024);Rect[] atlasRects = atlasTex.PackTextures(newTexs.ToArray(), 1, 4096);SpriteMetaData[] atlasSheets = new SpriteMetaData[atlasRects.Length];File.WriteAllBytes(atlasPath, atlasTex.EncodeToPNG());// 设置Atlas的spritefor (int i = 0; i < atlasSheets.Length; i++){SpriteMetaData t_Meta = new SpriteMetaData();t_Meta.name = sprites[i].name;t_Meta.rect = atlasRects[i];t_Meta.rect.Set(t_Meta.rect.x * atlasTex.width,t_Meta.rect.y * atlasTex.height,t_Meta.rect.width * atlasTex.width,t_Meta.rect.height * atlasTex.height);t_Meta.alignment = 9;Rect t_Rect = sprites[i].rect;t_Meta.pivot = new Vector2(sprites[i].pivot.x / t_Rect.width, sprites[i].pivot.y / t_Rect.height);atlasSheets[i] = t_Meta;}// 设置Atlas Texture属性TextureImporter atlas_Importer = AssetImporter.GetAtPath(atlasRelativePath) as TextureImporter;atlas_Importer.textureType = TextureImporterType.Sprite;atlas_Importer.spriteImportMode = SpriteImportMode.Multiple;//imp.textureCompression = TextureImporterCompression.Uncompressed;atlas_Importer.mipmapEnabled = false;atlas_Importer.spritesheet = atlasSheets;atlas_Importer.SaveAndReimport();AssetDatabase.ImportAsset(atlasRelativePath);AssetDatabase.Refresh();}}
}
结果:两张Atlas和一个单独的Sprite合并成最后一张大图集,其实前两张Atlas已经是合并过一次的了。
Anima2D数据迁移
这里就做简单的数据的位置偏移就可以了,伪代码如下。
Vector2 offset = new Vector2(newSprite.rect.x - oldSprite.rect.x, newSprite.rect.y - oldSprite.rect.y);
spriteMesh.sprite = newSprite;
spriteMeshData.pivotPoint += offset;
for (int k = 0; k < spriteMeshData.vertices.Length; k++)spriteMeshData.vertices[k] += offset;
SpriteMeshUtils.UpdateAssets(spriteMesh, spriteMeshData);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
这篇关于Unity - 模拟Sprite Packer合并多个Sprite的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!