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

相关文章

C#实现一键批量合并PDF文档

《C#实现一键批量合并PDF文档》这篇文章主要为大家详细介绍了如何使用C#实现一键批量合并PDF文档功能,文中的示例代码简洁易懂,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言效果展示功能实现1、添加文件2、文件分组(书签)3、定义页码范围4、自定义显示5、定义页面尺寸6、PDF批量合并7、其他方法

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

C#和Unity中的中介者模式使用方式

《C#和Unity中的中介者模式使用方式》中介者模式通过中介者封装对象交互,降低耦合度,集中控制逻辑,适用于复杂系统组件交互场景,C#中可用事件、委托或MediatR实现,提升可维护性与灵活性... 目录C#中的中介者模式详解一、中介者模式的基本概念1. 定义2. 组成要素3. 模式结构二、中介者模式的特点

Python批量替换多个Word文档的多个关键字的方法

《Python批量替换多个Word文档的多个关键字的方法》有时,我们手头上有多个Excel或者Word文件,但是领导突然要求对某几个术语进行批量的修改,你是不是有要崩溃的感觉,所以本文给大家介绍了Py... 目录工具准备先梳理一下思路神奇代码来啦!代码详解激动人心的测试结语嘿,各位小伙伴们,大家好!有没有想

MySQL进行分片合并的实现步骤

《MySQL进行分片合并的实现步骤》分片合并是指在分布式数据库系统中,将不同分片上的查询结果进行整合,以获得完整的查询结果,下面就来具体介绍一下,感兴趣的可以了解一下... 目录环境准备项目依赖数据源配置分片上下文分片查询和合并代码实现1. 查询单条记录2. 跨分片查询和合并测试结论分片合并(Shardin

基于Python实现进阶版PDF合并/拆分工具

《基于Python实现进阶版PDF合并/拆分工具》在数字化时代,PDF文件已成为日常工作和学习中不可或缺的一部分,本文将详细介绍一款简单易用的PDF工具,帮助用户轻松完成PDF文件的合并与拆分操作... 目录工具概述环境准备界面说明合并PDF文件拆分PDF文件高级技巧常见问题完整源代码总结在数字化时代,PD

Go语言使用select监听多个channel的示例详解

《Go语言使用select监听多个channel的示例详解》本文将聚焦Go并发中的一个强力工具,select,这篇文章将通过实际案例学习如何优雅地监听多个Channel,实现多任务处理、超时控制和非阻... 目录一、前言:为什么要使用select二、实战目标三、案例代码:监听两个任务结果和超时四、运行示例五

pandas数据的合并concat()和merge()方式

《pandas数据的合并concat()和merge()方式》Pandas中concat沿轴合并数据框(行或列),merge基于键连接(内/外/左/右),concat用于纵向或横向拼接,merge用于... 目录concat() 轴向连接合并(1) join='outer',axis=0(2)join='o

python运用requests模拟浏览器发送请求过程

《python运用requests模拟浏览器发送请求过程》模拟浏览器请求可选用requests处理静态内容,selenium应对动态页面,playwright支持高级自动化,设置代理和超时参数,根据需... 目录使用requests库模拟浏览器请求使用selenium自动化浏览器操作使用playwright

MySQL多实例管理如何在一台主机上运行多个mysql

《MySQL多实例管理如何在一台主机上运行多个mysql》文章详解了在Linux主机上通过二进制方式安装MySQL多实例的步骤,涵盖端口配置、数据目录准备、初始化与启动流程,以及排错方法,适用于构建读... 目录一、什么是mysql多实例二、二进制方式安装MySQL1.获取二进制代码包2.安装基础依赖3.清