unity美术资源优化(资源冗余,主界面图集过多)

news2024/12/30 0:58:04
图片资源冗余:

UPR unity的性能优化工具检查资源
在这里插入图片描述

1.检查纹理读/写标记
开启纹理资源的读/写标志会导致双倍的内存占用
检查Inspector -> Advanced -> Read/Write Enabled选项

2.检查纹理资源alpha通道
如果纹理的alpha通道全部为0,或者全部为255,可以认为其中不包含有效信息,此时应禁用’Alpha源’标志,否则会浪费这部分的内存。
检查Inspector -> Alpha Source选项

3.检查纯色纹理
纯色纹理的使用可能可以由一些设置来代替。由于某些情况下纯色纹理是必不可少的,此警告仅会在所使用的纹理较大(大于设定值, 默认为16x16)时才会触发。
Custom Parameters: heightThreshold : 16widthThreshold : 16

4.检查重复纹理

问题1 方案:可继承AssetPostprocessor对资源改动的时候检查是否有开启读/写标记

问题2,3 ,4 方案:定期检查
其中问题2,3只需要判断颜色通道比较简单不做解释
问题4 解决:
1.遍历所有贴图 用字典缓存 找到重复的资源
2.找到项目下所有材质,并且缓存
3.找到引用该重复贴图的材质
4.判断该材质所有引用贴图字段 如有和重复贴图相同 则替换
5.删除重复贴图

代码:

static void RemoveReportTexture(string[] searchInFolders)
    {
        Dictionary<string, string> md5dic = new Dictionary<string, string>();
        HashSet<int> deleteTexInsId = new HashSet<int>();
        //string[] guids = AssetDatabase.FindAssets("t:Texture", new string[] { "Assets/actor", "Assets/FX", "Assets/scene", });
        string[] guids = AssetDatabase.FindAssets("t:Texture", searchInFolders);
        string[] matFiles = null;
        string[] matFilesContent = null;
        //Debug.Log("贴图" + guids.Length);
        //1.遍历所有贴图 用字典缓存 找到重复的资源 
        int progress = 0;
        foreach (var assetGuid in guids)
        {
            string assetPath = AssetDatabase.GUIDToAssetPath(assetGuid); // 从GUID拿到资源的路径
            bool isCancel = EditorUtility.DisplayCancelableProgressBar("移除重复的贴图", assetPath, (float)progress / (float)guids.Length);
            progress++;
            string md5 = GetMD5Hash(Path.Combine(Directory.GetCurrentDirectory(), assetPath)); //获取md5
            string path;
            md5dic.TryGetValue(md5, out path);
            if (path == null)
            {
                md5dic[md5] = assetPath;
                // Debug.Log(assetPath);
            }
            else
            {
                Debug.LogFormat("资源重复{0},{1}", path, assetPath);
                if (matFiles == null)
                {
                    //2.找到所有材质,并且缓存
                    List<string> withoutExtensions = new List<string>() { ".mat" };
                    matFiles = Directory.GetFiles(Application.dataPath, "*.*", SearchOption.AllDirectories).Where(s => withoutExtensions.Contains(Path.GetExtension(s).ToLower())).ToArray();
                    matFilesContent = new string[matFiles.Length];
                    for (int i = 0; i < matFiles.Length; i++)
                    {
                        matFilesContent[i] = File.ReadAllText(matFiles[i]);
                    }
                }
                Texture2D tex = AssetDatabase.LoadAssetAtPath<Texture2D>(path); //保留的图
                Texture2D deleteTex = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath); //删除的图
                //3.找到引用该贴图的所有材质
                for (int startIndex = 0; startIndex < matFiles.Length; startIndex++)
                {
                    string file = GetRelativeAssetsPath(matFiles[startIndex]);

                    if (Regex.IsMatch(matFilesContent[startIndex], assetGuid))
                    {
                        Material material = AssetDatabase.LoadAssetAtPath<Material>(file);
                        bool isUseTex = false;
                        var textureNames = material.GetTexturePropertyNames();
                        //Debug.Log("遍历所有需要修改替换贴图的材质:" + file + ",贴图数:" + textureNames.Length);
                        //4.判断该材质所有引用贴图字段 如有和重复贴图相同 则替换
                        for (int j = 0; j < textureNames.Length; j++)
                        {
                            if (material.HasTexture(textureNames[j])) // 该方法获取不到不属于该shader的贴图(切换材质后unity会保留之前shader的信息)
                            {
                                Texture texture = material.GetTexture(textureNames[j]); // 获取材质上的贴图引用
                                if (texture != null)
                                {
                                    //Debug.Log("获取到图片名字:" + texture.name);
                                    if (texture.name == deleteTex.name)
                                    {
                                        isUseTex = true;
                                        material.SetTexture(textureNames[j], tex);
                                        Debug.Log("修改的材质:" + file + "的贴图" + assetPath + ",assetGuid:" + assetGuid + ",替换为:" + path + "修改材质propertyName:" + textureNames[j]);
                                        EditorUtility.SetDirty(material);
                                    }
                                }
                            }
                        }
                    }
                }

                //5.替换完所有材质,删除该重复贴图
                //if(isChangeSucceedCount != referencesMatPath.Count)
                //{
                //    Debug.LogError("+++修改失败+++isChangeSucceedCount:"+ isChangeSucceedCount+ "+++referencesMatPath.Count:" + referencesMatPath.Count);
                //}
                //else
                //{
                //    AssetDatabase.DeleteAsset(assetPath);
                //    Debug.LogError("+++修改成功+++");
                //}
                Debug.Log("+++DeleteAsset+++:" + assetPath);
                deleteTexInsId.Add(deleteTex.GetInstanceID());
                AssetDatabase.DeleteAsset(assetPath);
            }
        }
        AssetDatabase.SaveAssets();
        EditorUtility.ClearProgressBar();

        if (deleteTexInsId.Count > 0)
        {
            int checkProgress = 0;
            for (int startIndex = 0; startIndex < matFiles.Length; startIndex++)
            {
                string file = GetRelativeAssetsPath(matFiles[startIndex]);
                bool isCancel = EditorUtility.DisplayCancelableProgressBar("检查材质是否缺少贴图", file, (float)checkProgress / (float)matFiles.Length);
                checkProgress++;

                Material material = AssetDatabase.LoadAssetAtPath<Material>(file);

                SerializedObject serializedMaterial = new SerializedObject(material);
                SerializedProperty texturesProperty = serializedMaterial.FindProperty("m_SavedProperties.m_TexEnvs");

                foreach (SerializedProperty textureProperty in texturesProperty)
                {
                    string propertyName = textureProperty.displayName;
                    SerializedProperty textureReference = textureProperty.FindPropertyRelative("second.m_Texture");

                    // 检查贴图引用是否丢失
                    if (material.shader.FindPropertyIndex(propertyName) > 0 && textureReference.objectReferenceValue == null && deleteTexInsId.Contains(textureReference.objectReferenceInstanceIDValue))
                    {
                        Debug.LogError($"移除重复的模型贴图导致 Missing texture in material: {material.name}, Property: {propertyName}");
                    }
                }
            }
            EditorUtility.ClearProgressBar();
        }
    }

主界面图集过多

在这里插入图片描述

主界面UI也就几个界面,但通过unity的Memory Profiler去看内存的时候 却发现了30个左右的图集,原因是因为拼接资源的时候没注意导致一个界面依赖了好几个图集,简单解决就是把主界面和其他界面一起用到的图片放到公用图集里去,然后就调整对应的图集,代码,界面

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1948290.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

了解Selenium中的WebElement

Selenium中到处都使用WebElement来执行各种操作。什么是WebElement&#xff1f;这篇文章将详细讨论WebElement。 Selenium中的WebElement是一个表示网站HTML元素的Java接口。HTML元素包含一个开始标记和一个结束标记&#xff0c;内容位于这两个标记之间。 HTML元素的重命名 …

C++图网结构算法

目录 一.迪杰斯特拉算法&#xff08;dijkstra&#xff09; 1.实现原理&#xff1a; 2.代码实现&#xff1a; 3.例题&#xff1a; 二.spfa算法&#xff1a; 1.实现原理&#xff1a; 2.代码实现&#xff1a; 3.例题&#xff1a; 三.贝尔曼福特&#xff08;bellman_ford&…

HTTP模块(二)

HTTP 设置 HTTP 响应报文 HTTP报文常见属性&#xff1a; const http require(http);const server http.createServer((request, response) > {// 设置请求状态码 2xx 4xx 5xxresponse.statusCode 200;// 设置请求描述 了解即可response.statusMessage hello// 指定响…

Nodepad++运行Python文件的方法

windows中使用nodepad运行python文件 首先&#xff0c;需要在windows中安装python解释器。 然后打开nodepad&#xff0c;新建一个文件&#xff0c;输入一段测试的python代码 import socketdef get_hostname():try:# 获取主机名hostname socket.gethostname()return hostna…

uniapp集成安卓原生录屏插件以及使用

概述 我们知道UniApp的出现简化了开发者的工作流程&#xff0c;并减少了代码的重复编写。开发者可以使用一套代码编译到iOS、Android、以及各种小程序的应用&#xff0c;节省了人力和时间成本&#xff0c;但是涉及到与系统交互的时候&#xff0c;比如录屏、录音、录像、文件操…

Go语言常见序列化协议全面对比

先说结论 从易用性、性能、内存占用、编码后大小等几个方面综合考虑 ProtoBuf 胜出。 Gob 从性能和 I/O 带宽占用上都和 ProtoBuf 差不多&#xff0c;唯一劣势是编解码时内存占用较多。考虑到不用再写 IDL 带来的易用性&#xff0c;如果整个系统内不存在使用除 Go 以外其他语言…

『Django』搭建你的博客网站

theme: smartblue 点赞 关注 收藏 学会了 本文简介 如果你学了我前面写的 Django 文章&#xff0c;现在已经有能力去试试自己搭建博客网站了。 虽然用的不是现在流行的前后端分离的方式(前后端分离的方式会在之后的文章讲解)。 但在搭建网站之前我们还要做一些额外的功能让你…

【机器学习】梯度下降的基本概念和如何使用梯度下降自动化优化w和b

引言 梯度下降是一种用于寻找函数最小值的优化算法&#xff0c;它在机器学习中广泛用于训练模型&#xff0c;如线性回归、神经网络等 一、梯度下降的基本概念 1.1 目标函数 在机器学习中&#xff0c;这通常是损失函数&#xff08;如均方误差、交叉熵等&#xff09;&#xff0…

[渗透测试] 主动信息收集

主动信息收集 在红蓝对抗过程中&#xff0c;资产属于核心地位&#xff0c;攻击方&#xff08;红方&#xff09;要尽可能的去获取对方资产&#xff0c;暴露目标资产&#xff0c;包括IP地址、网络设备、安全设备、服务器、存储在服务器中的数据等。防守方也要清楚自己有多少有价…

了解网络是如何运作

“Web 的工作原理”提供了一个简化的视图,用于了解在计算机或手机上的 Web 浏览器中查看网页时发生的情况。 这个理论对于短期内编写 Web 代码来说并不是必需的,但不久之后,你就会真正开始从理解后台发生的事情中受益。 客户端和服务器 连接到 Internet 的计算机称为客户端和…

dns逆向解析,主从服务,多域名访问(穿插ntp服务器)

复习 域名解析&#xff1a; 正向解析&#xff1a;将域名解析为ip 反向解析&#xff1a;将ip解析为域名 逆向解析 关闭防火墙和selinux&#xff0c;配置静态ip [rootdns ~]# vim /etc/named.rfc1912.zones [rootdns ~]# vim /etc/named.conf [rootdns ~]# cd /var/named/ [rootd…

刚购买的阿里云服务器该如何配置环境(CentOS)

文章目录 购买开始初始设置登录云服务器安装 Apache 服务安装 MySQL安装 PHP快照 第三方 SSH 登录笔者的话 购买 按照需求购买就行。学生有免费试用一个月的活动&#xff0c;可以试着玩玩。 开始初始设置 登录云服务器 购买完后&#xff0c;点击实例&#xff0c;点击实例名…

Linux下RDMA驱动程序探索系列-2

本系列文章将带领读者逐步了解Linux操作系统下的RDMA子系统。本篇文章作为系列的第二篇&#xff0c;将深入内核态驱动程序的代码&#xff0c;主要介绍如下内容&#xff1a; Driver的初始化流程几个重要verbs回调函数的简介 01、Kernel Driver的初始化流程 由于不同厂商的驱动…

进销存系统开发,含税小计和含税单价计算,含税和不含税,1000元电脑为案例

if (data ! null) {console.log("中断调试&#xff0c;2024-7-25 最终计算税务");//删除不需要会报错var 未来之窗_人工智能_计算_税额 parseFloat((data.price * data.num * data.tax_rate / 100 ).toFixed(2));var 未来之窗_人工智能_计算_含税小计 parseFloat((…

js轮播图制作

实现一个简单的JavaScript轮播图可以通过以下步骤完成&#xff1a; 创建HTML结构&#xff0c;包括轮播图容器和图片列表。 使用CSS进行样式设置&#xff0c;包括隐藏多余的图片。 使用JavaScript编写函数来控制图片的切换。

07-15 周一 lmdeploy导出迁移因子到量化模型中

07-15 周一 lmdeploy导出迁移因子到量化模型中 时间版本修改人描述2024年7月15日14:57:02V0.1宋全恒新建文档 简介 方案设计 由于norm层的前后导致smoothquant执行量化不好融合&#xff0c;为了降低我事先的难度&#xff0c;所以就不再融合normalization的算子了&#xff0c…

vue3编程-import.meta.glob实现动态路由(菜单)

import.meta.glob 是vite提供的批量懒加载组件的方法 本地开发环境&#xff1a; const modules import.meta.glob(../views/**/*.vue)这段代码返回的modules是一个Map&#xff1a; key是vue文件的相对路径&#xff0c;值是一个函数&#xff0c;将函数打印出来&#xff0c;如…

【微信小程序实战教程】之微信小程序原生开发详解

微信小程序原生开发详解 微信小程序的更新迭代非常频繁&#xff0c;几乎每个月都会有新版本发布&#xff0c;这就会让初学者感觉到学习的压力和难度。其实&#xff0c;我们小程序的每次版本迭代都是在现有小程序架构基础之上进行更新的&#xff0c;如果想要学好小程序开发技术&…

配置mysql8.0.21版本docker-compose启动容器

1. 总览 2 docker-compose.xml配置 version: 3 services:mysql:image: 192.168.188.131:8000/mysqlrestart: alwaysvolumes:- ./data:/var/lib/mysql- ./my.cnf:/etc/mysql/my.cnf- ./mysql-files:/var/lib/mysql-files- ./log/mysql:/var/log/mysqlenvironment:MYSQL_ROOT_PA…

Shell实现服务自动部署

一、环境 注意&#xff1a; nfs.example.com应该为nfs.exam.com 172.25.250.101-172.25.250.105 共 5 个 IP 地址由servera.exam.com服务器进行提供。 172.25.250.106 由 serverb.exam.com 服务器进行提供。 二、需求 项目需求&#xff1a; 1. 172.25.250.101 主机上的 W…