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

相关文章

CSS模拟 html 的 title 属性(鼠标悬浮显示提示文字效果)

《CSS模拟html的title属性(鼠标悬浮显示提示文字效果)》:本文主要介绍了如何使用CSS模拟HTML的title属性,通过鼠标悬浮显示提示文字效果,通过设置`.tipBox`和`.tipBox.tipContent`的样式,实现了提示内容的隐藏和显示,详细内容请阅读本文,希望能对你有所帮助... 效

使用Apache POI在Java中实现Excel单元格的合并

《使用ApachePOI在Java中实现Excel单元格的合并》在日常工作中,Excel是一个不可或缺的工具,尤其是在处理大量数据时,本文将介绍如何使用ApachePOI库在Java中实现Excel... 目录工具类介绍工具类代码调用示例依赖配置总结在日常工作中,Excel 是一个不可或缺的工http://

使用Python创建一个能够筛选文件的PDF合并工具

《使用Python创建一个能够筛选文件的PDF合并工具》这篇文章主要为大家详细介绍了如何使用Python创建一个能够筛选文件的PDF合并工具,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录背景主要功能全部代码代码解析1. 初始化 wx.Frame 窗口2. 创建工具栏3. 创建布局和界面控件4

Python自动化办公之合并多个Excel

《Python自动化办公之合并多个Excel》在日常的办公自动化工作中,尤其是处理大量数据时,合并多个Excel表格是一个常见且繁琐的任务,下面小编就来为大家介绍一下如何使用Python轻松实现合... 目录为什么选择 python 自动化目标使用 Python 合并多个 Excel 文件安装所需库示例代码

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

linux下多个硬盘划分到同一挂载点问题

《linux下多个硬盘划分到同一挂载点问题》在Linux系统中,将多个硬盘划分到同一挂载点需要通过逻辑卷管理(LVM)来实现,首先,需要将物理存储设备(如硬盘分区)创建为物理卷,然后,将这些物理卷组成... 目录linux下多个硬盘划分到同一挂载点需要明确的几个概念硬盘插上默认的是非lvm总结Linux下多

mysqld_multi在Linux服务器上运行多个MySQL实例

《mysqld_multi在Linux服务器上运行多个MySQL实例》在Linux系统上使用mysqld_multi来启动和管理多个MySQL实例是一种常见的做法,这种方式允许你在同一台机器上运行多个... 目录1. 安装mysql2. 配置文件示例配置文件3. 创建数据目录4. 启动和管理实例启动所有实例

使用Python合并 Excel单元格指定行列或单元格范围

《使用Python合并Excel单元格指定行列或单元格范围》合并Excel单元格是Excel数据处理和表格设计中的一项常用操作,本文将介绍如何通过Python合并Excel中的指定行列或单... 目录python Excel库安装Python合并Excel 中的指定行Python合并Excel 中的指定列P

使用SQL语言查询多个Excel表格的操作方法

《使用SQL语言查询多个Excel表格的操作方法》本文介绍了如何使用SQL语言查询多个Excel表格,通过将所有Excel表格放入一个.xlsx文件中,并使用pandas和pandasql库进行读取和... 目录如何用SQL语言查询多个Excel表格如何使用sql查询excel内容1. 简介2. 实现思路3