Unity3D性能优化-图集制作插件TexturePacker中文教程

简介: 本文提供全流程,中文翻译。Chinar Unity图集制作插件-TexturePacker图文教程 学习如何使用 TexturePacker 为 Unity 制作图集 为新手节省宝贵的时间,避免采坑! 简单说就是:将大量的小图,合并到一张大图上,可以有效的降低 Drawcall 1.

Chinar blog www.chinar.xin

TexturePacker
Unity 图集制作工具


本文提供全流程,中文翻译

Chinar 的初衷是将一种简单的生活方式带给世人

使有限时间 具备无限可能

Chinar —— 心分享、心创新!

助力快速利用 C# 判断用户电脑联网状态

给新手节省宝贵的时间,避免采坑!


Chinar 教程效果:
8_


全文高清图片,点击即可放大观看 (很多人竟然不知道)


1

Intro —— 简介


为什么使用图集?

简单说就是:将大量的小图,合并到一张大图上,可以有效的降低 Drawcall

绘制一个图像需要提交图片(纹理)到显存,然后再进行绘制显示到屏幕上

在这个过程中 CPU 会产生一次 DrawCall ,也就是说绘制 88 张图片就要产生 88 次DrawCall

这显然非常消耗性能。图集就是为了解决此类问题

1. 减少性能消耗
2. 分类明确,易于管理
3.一次加载或者卸载完成多图片的处理,提高了运行效率

Unity 官方模糊了图集的概念,使开发者专注于开发,在打包时才会将图片进行合并

自行打包图集,网络大神各抒己见,皆有特色,想要官方的可以自行搜索

Chinar 的风格大家都懂,什么高效来什么!只为大家介绍更为好用的插件

我们今天的主角:TexturePacker、TexturePackerImporter


2

Download —— 下载、安装



TexturePacker 是一个独立的软件程序,支持多个引擎,安装后记得选择Unity平台

TexturePackerImporterUnity Store中免费插件,搜索下载导入工程即可

举个例子

点击下载 —— TexturePacker (官网)

点击下载 —— TexturePacker X64 (Chinar免费)
2_TexturePacker_
2_1_


3

Import Plugin —— 导入插件


TexturePacker 安装完成后,打开先不管,我们先来创建一个Unity工程,导入TexturePackerImporter

Ctrl+9 快捷键 打开 Asset Store 资源商店

→→搜索 TexturePacker Importer,下载并导入工程

先导入这个插件是为了适配之后 TexturePacker 生成并导入Unity 中的文件。直接进行处理,使一张大图自动切分
举个例子
3_TexturePacker_Importer


4

Texture usage —— 软件用法


我们回到 TexturePacker 软件界面,来简单学习下如何制作与导出文件

图片直接拖进来,算法会自动将所有小图切割合并到一张大图中,细节 Chinar 做的图已经很详细了

最后点击publish sprite sheet 会将生成的图集数据文件直接放到我们选择的目录中

(推荐直接放到 Unity 项目中。为了规范性,Chinar 放在了 Resources/Texture/Atlas 下)

举个例子
4_TexturePacker_
4_1_


5

Unity Project —— 项目数据


切换到 Unity 软件界面,等待文件编译

由于我们之前先导入了 TexturePacker Importer ,所以图片数据导入到 Unity 中会自动切分,我们只需直接使用即可

直接将sprite拖到UI image 组件上即可,用法上没什么不同

举个例子
5_0Unity_


6

dynamic loading —— 动态加载 Sprite


多数情况下,除了通过拖拽的方式,我们还需要用代码来动态的改变 UI 元素

很多大神,提出直接将UI做成预设物,通过加载预设的方式来实现动态改变UI。这样做有优点也有缺点,对于初学者来讲维护不方便,而且需要建立大量的预设物,量大后会造成不便。

Chinar 推荐方式:

注意: 需将图集文件放在 Resources / 其子目录下,用数据类型散列表(字典) Dictionary 来记录实现,动态加载图片
举个例子
6_Resources


7

Lookup function —— 查找函数


我们需要一个查找函数,以便我们获取目标图集中的对应精灵

重点函数:Object[] atlas = Resources.LoadAll(spriteAtlasPath);
目录中,图片数据 “Chinar”是一张.png图片 ,需放在 Resources 目录下
因图片是单个文件, 如果用 Resources.Load只能返回一个 Object 对象,这里采用 Resources.LoadAll 返回 Object[]

我封装了一个极简的静态通用函数,适用于内外部数据的读取,无需挂载直接调用

将获取对应名称的 UI Sprite 简化到一行代码

LoadSprite(string atlasPath, string spriteName, bool isResources = true)

举个例子

using UnityEngine;
using System.Collections.Generic;


/// <summary>
/// 静态函数,无需挂载
/// 主函数:LoadSprite()
/// </summary>
public class ChinarAtlas
{
    private static readonly Dictionary<string, Object[]> _atlasDic = new Dictionary<string, Object[]>(); //图集字典


    /// <summary>
    /// 加载对应图集中,对应名称的精灵图片
    /// </summary>
    /// <param name="atlasPath">图集路径</param>
    /// <param name="spriteName">精灵名称</param>
    /// <param name="isResources">默认内部 Resources 加载,false 时,通过 AssetBundle 方式加载</param>
    /// <returns>Sprite</returns>
    public static Sprite LoadSprite(string atlasPath, string spriteName, bool isResources = true)
    {
        Sprite sprite                                = null;                                                               //字典中包含 目标图集
        if (_atlasDic.ContainsKey(atlasPath)) sprite = SpriteFormAtlas(_atlasDic[atlasPath], spriteName);                  //得到该图集中对应名称的 Sprite
        if (sprite != null) return sprite;                                                                                 //返回找到的 Sprite
        Object[] atlas = isResources ? Resources.LoadAll(atlasPath) : AssetBundle.LoadFromFile(atlasPath).LoadAllAssets(); //选择内外部加载方式
        _atlasDic.Add(atlasPath, atlas);                                                                                   //到字典中
        sprite = SpriteFormAtlas(atlas, spriteName);                                                                       //找到 Sprite
        return sprite;                                                                                                     //返回找到的 Sprite
    }


    /// <summary>
    /// 删除图集缓存
    /// </summary>
    /// <param name="atlasPath">图集路径</param>
    public static void DeleteAtlas(string atlasPath)
    {
        if (_atlasDic.ContainsKey(atlasPath)) _atlasDic.Remove(atlasPath);
    }


    /// <summary>
    /// 遍历图集并找出 Sprite
    /// </summary>
    /// <param name="atlas">Object[]</param>
    /// <param name="spriteName">精灵名称</param>
    /// <returns>Sprite</returns>
    private static Sprite SpriteFormAtlas(Object[] atlas, string spriteName)
    {
        foreach (var obj in atlas)
        {
            if (obj != null && obj is Sprite && obj.name == spriteName) return (Sprite) obj;
        }

        Debug.LogWarning("图集中未查找到名为:<" + spriteName + ">的精灵");
        return null;
    }
}

8

Dynamic loading usage —— 动态加载用法


直接调用函数 ChinarAtlas.LoadSprite(图集文件全路径,目标Sprite名称,(不填) 默认Resources加载/false 是AssetBundle)

极尽封装,就是这么简单
举个例子

using UnityEngine;
using UnityEngine.UI;


/// <summary>
/// 动态读取数据、添加/改变UI元素
/// </summary>
public class ChinarDemo : MonoBehaviour
{
    private AssetBundle ab; //AB包对象


    public Image UiResourcesImage
    {
        get { return GameObject.Find("Resources Image").GetComponent<Image>(); }
    }

    public Image UiAssetBundleImage
    {
        get { return GameObject.Find("AssetBundle Image").GetComponent<Image>(); }
    }


    void Start()
    {
        ResourcesLoadMethod();
        AssetBundleLoadMethod();
    }


    /// <summary>
    /// 第一种:Resources加载 —— 内部 
    /// </summary>
    private void ResourcesLoadMethod()
    {
        UiResourcesImage.sprite = ChinarAtlas.LoadSprite("Texture/Atlas/Chinar", "Chinar1");
    }


    /// <summary>
    /// 第二种:AssetBundle加载 —— 外部 
    /// </summary>
    private void AssetBundleLoadMethod()
    {
        UiAssetBundleImage.sprite = ChinarAtlas.LoadSprite(Application.streamingAssetsPath + "/ChinarAssetBundles/atlas/chinar.unity3d", "Chinar2", false);
    }
}

8_


9

Share —— 项目分享



项目文件为 unitypackage 文件包:

下载导入 Unity 即可使用

举个例子
Git

CSDN (积分支持)

NetDisk (Chinar 免费)


10

AssetBundle —— AB包知识 (扩展)


如果是初学者不太了解 AssetBundle 知识的话

给大家提供2个教程。便于学习 打包、读取
举个例子

Unity 打包 AssetBundle 资源教程

Unity 读取 AssetBundle 资源教程(所有读取方式)


支持

May Be —— 开发者,总有一天要做的事!


拥有自己的服务器,无需再找攻略

Chinar 提供一站式《零》基础教程

使有限时间 具备无限可能!

Chinar 知你所想,予你所求!( Chinar Blog )


END

本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究

对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: ichinar@icloud.com

对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址

相关文章
|
编解码 程序员 atlas
Unity 之 图集属性详解和代码示例 -- 拓展一键自动打包图集工具
图集只是当所有给低昂的纹理需要相同的着色器时采用的一种方法,如果一些纹理需要通过着色器应用独立的图形效果,它们就必须分离到自己的材质中,并在单独的组中打图集。
1416 0
Unity 之 图集属性详解和代码示例 -- 拓展一键自动打包图集工具
|
JavaScript 前端开发 程序员
用Unity不会几个插件怎么能行?Unity各类插件及教程推荐
话说工欲善其事必先利其器,程序员总是有一些开发利器,而对于Unity3D开发程序员来说,插件就是非常好用的利器。 今天博主,就将比较好用的插件推荐给大家,希望一起学习品鉴。
|
XML 编解码 编译器
Unity跨平台UI解决方案:可能是最全的FairyGUI系列教程-第八天
众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣!!!
1489 0
|
8月前
|
持续交付 图形学 开发者
【Unity实战系列】Unity的下载安装以及汉化教程
【Unity实战系列】Unity的下载安装以及汉化教程
212 0
|
8月前
|
数据可视化 C# 图形学
【unity造轮子】Unity ShaderGraph使用教程与各种特效案例
点关注不迷路,持续输出干货文章。 嗨,大家好,我是向宇。最近在玩ShaderGraph,决定把我自己实验的所有效果记录到这篇博客中,附带完整高清的连线动态图,希望对想要学习ShaderGraph的同学有所启发。后续有发现一些新的ShaderGraph我还会继续进行更新。
|
存储 负载均衡 安全
【Unity干货教程】如何实现Unity和Android原生互相调用?
Unity是一个跨平台开发工具,发布到移动平台也是大部分Unity开发者的必备技能。而由于Unity跨平台的特性,总会遇到在移动平台的技术细节支持不够,或者需要在调用其他原生插件的情况。这里我们说一下如何在Android Studio中创建一个可供Unity调用的aar插件,以实现Unity和Android原生互相调用的目的。
|
图形学 Windows
很好用的Unity编辑器扩展工具 Odin Inspector教程
Odin包含许多功能,例如Static Inspector,Project Validation,Odin Editor Windows和我们的开源Odin Serializer,它允许您在需要多态对象结构时扩展Unity的序列化功能,或者希望在运行时序列化和反序列化数据。
很好用的Unity编辑器扩展工具 Odin Inspector教程
|
存储 设计模式 缓存
Unity面试题——Unity性能优化
Unity面试题——Unity性能优化
327 0
|
图形学 异构计算
Unity【LOD Group】- 关于性能优化中LOD的使用与总结
Unity【LOD Group】- 关于性能优化中LOD的使用与总结
596 0
Unity【LOD Group】- 关于性能优化中LOD的使用与总结
|
图形学
Unity3D教程:回合制游戏实现
一、场景布置 首先是简单的场景布置,在3D部分很简单。就几个简单的基本组件,在一个Plane上面放2个Cube,并且上不同颜色的纯色Material。唯一需要大家注意的是,请将两个Cube改好名,以免到时候编程不知道哪个跟哪个。
1636 0