Unity - 模拟Sprite Packer合并多个Sprite

2023-12-01 19:10

本文主要是介绍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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/442355

相关文章

Python函数返回多个值的多种方法小结

《Python函数返回多个值的多种方法小结》在Python中,函数通常用于封装一段代码,使其可以重复调用,有时,我们希望一个函数能够返回多个值,Python提供了几种不同的方法来实现这一点,需要的朋友... 目录一、使用元组(Tuple):二、使用列表(list)三、使用字典(Dictionary)四、 使

Python使用pynput模拟实现键盘自动输入工具

《Python使用pynput模拟实现键盘自动输入工具》在日常办公和软件开发中,我们经常需要处理大量重复的文本输入工作,所以本文就来和大家介绍一款使用Python的PyQt5库结合pynput键盘控制... 目录概述:当自动化遇上可视化功能全景图核心功能矩阵技术栈深度效果展示使用教程四步操作指南核心代码解析

Python中合并列表(list)的六种方法小结

《Python中合并列表(list)的六种方法小结》本文主要介绍了Python中合并列表(list)的六种方法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋... 目录一、直接用 + 合并列表二、用 extend() js方法三、用 zip() 函数交叉合并四、用

Python模拟串口通信的示例详解

《Python模拟串口通信的示例详解》pySerial是Python中用于操作串口的第三方模块,它支持Windows、Linux、OSX、BSD等多个平台,下面我们就来看看Python如何使用pySe... 目录1.win 下载虚www.chinasem.cn拟串口2、确定串口号3、配置串口4、串口通信示例5

利用Python实现Excel文件智能合并工具

《利用Python实现Excel文件智能合并工具》有时候,我们需要将多个Excel文件按照特定顺序合并成一个文件,这样可以更方便地进行后续的数据处理和分析,下面我们看看如何使用Python实现Exce... 目录运行结果为什么需要这个工具技术实现工具的核心功能代码解析使用示例工具优化与扩展有时候,我们需要将

Python实现获取带合并单元格的表格数据

《Python实现获取带合并单元格的表格数据》由于在日常运维中经常出现一些合并单元格的表格,如果要获取数据比较麻烦,所以本文我们就来聊聊如何使用Python实现获取带合并单元格的表格数据吧... 由于在日常运维中经常出现一些合并单元格的表格,如果要获取数据比较麻烦,现将将封装成类,并通过调用list_exc

Java中Switch Case多个条件处理方法举例

《Java中SwitchCase多个条件处理方法举例》Java中switch语句用于根据变量值执行不同代码块,适用于多个条件的处理,:本文主要介绍Java中SwitchCase多个条件处理的相... 目录前言基本语法处理多个条件示例1:合并相同代码的多个case示例2:通过字符串合并多个case进阶用法使用

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

基于Flask框架添加多个AI模型的API并进行交互

《基于Flask框架添加多个AI模型的API并进行交互》:本文主要介绍如何基于Flask框架开发AI模型API管理系统,允许用户添加、删除不同AI模型的API密钥,感兴趣的可以了解下... 目录1. 概述2. 后端代码说明2.1 依赖库导入2.2 应用初始化2.3 API 存储字典2.4 路由函数2.5 应

Python实现合并与拆分多个PDF文档中的指定页

《Python实现合并与拆分多个PDF文档中的指定页》这篇文章主要为大家详细介绍了如何使用Python实现将多个PDF文档中的指定页合并生成新的PDF以及拆分PDF,感兴趣的小伙伴可以参考一下... 安装所需要的库pip install PyPDF2 -i https://pypi.tuna.tsingh