一次【自定义编辑器功能脚本】【调用时内存爆仓】事故排查

一 、事故描述

我有一个需求:在工程文件中找得到所有的图片(Texture 2D),然后把WebGL发布打包时的图片压缩规则进行修改。
项目中有图片2千多张,其中2k分辨率的图片上百张,当我右键进行批量处理的时候,内存蹭蹭蹭往上冒,直接吃满,然后显示Unity挂掉,接着其他程序也会挂,最后电脑卡住…

二、原因分析

当我全选整个项目中的图片,然后右键菜单执行该脚本后,它加载图片的代码如下:

 Object[] textures = Selection.GetFiltered(typeof(Texture2D), SelectionMode.DeepAssets);

这个数组会爆仓内存。

其次:每张图单独处理的时候,我new了两个东西,如下

new的第一个组件

// 创建特定平台压缩实例
TextureImporterPlatformSettings platformSettings = new TextureImporterPlatformSettings();
//设置属性

new的第二个组件

//设置importSettings
TextureImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(texture)) as TextureImporter;
//设置属性

这两个组件是在一个for循环里面,用完之后,没有设置为null。

三、换种思路

  • 1、只抓取资源id
string[] guids = AssetDatabase.FindAssets("t:texture2d");
  • 2、用id取获取图片对象
Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
  • 3、new 出来的组件记得清空
Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>(path) ;
TextureImporterPlatformSettings platformSettings = new TextureImporterPlatformSettings();
TextureImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(texture)) as TextureImporter;//属性赋值
//.....//-----------------清空对象-----------------至于什么时候触发GC,那就不知道了
platformSettings = null;
importer = null;
texture = null;
  • 3、图片上的组件用完及时清空
  static void FindAllTexture2D(){//****************************************参数设置区**********begin//TODO 做成EditWindow类型TextureImporterFormat format = TextureImporterFormat.ASTC_12x12; //图片压缩格式int compressionQuality = 60; //压缩比例string platform = "WebGL"; //发布的平台 //************************************************************end//查找工程文件中的所有精灵图片string[] guids = AssetDatabase.FindAssets("t:texture2d");Debug.Log($"Found {guids.Length} Texture2d assets.");foreach (string guid in guids){try{string path = AssetDatabase.GUIDToAssetPath(guid);Debug.Log($"{path}");// 使用AssetDatabase加载Texture2DTexture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>(path);//Debug.Log($"{texture.name}");if (texture == null) continue;// 创建特定平台压缩实例TextureImporterPlatformSettings platformSettings = new TextureImporterPlatformSettings();platformSettings.overridden = true;platformSettings.name = platform;// 设置为压缩platformSettings.textureCompression = TextureImporterCompression.Compressed;// 设置压缩格式platformSettings.format = format; //TextureImporterFormat.ASTC_12x12;platformSettings.compressionQuality = compressionQuality; //40platformSettings.maxTextureSize = GetMaxSize(texture as Texture2D); //32//设置importSettingsTextureImporter importer =AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(texture)) as TextureImporter;if (importer == null) continue;importer.SetPlatformTextureSettings(platformSettings);//Apply 设置importer.SetPlatformTextureSettings(platformSettings);//保存资源importer.SaveAndReimport();//资源清空platformSettings = null;importer = null;texture = null;}catch (Exception ex){Debug.Log( $" ~~~~~error~~~~~ 设置报错:{ex.Message}");}}}

四、附录:出错的脚本

using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;public class SetTextureCompression
{//****************************************参数设置区**********begin//TODO 做成EditWindow类型private static TextureImporterFormat format = TextureImporterFormat.ASTC_12x12;  //图片压缩格式private static int compressionQuality = 60;                                      //压缩比例private static string platform = "WebGL";                                        //发布的平台 //************************************************************end/// <summary>/// 设置贴图在build时的压缩选项/// </summary>[MenuItem("Assets/设置发布WebGL时贴图的压缩格式")]static void SetCompression(){int count = 0;Object[] textures = Selection.GetFiltered(typeof(Texture2D), SelectionMode.DeepAssets);if (textures.Length > 0){foreach (Object texture in textures){// 创建特定平台压缩实例TextureImporterPlatformSettings platformSettings = new TextureImporterPlatformSettings();platformSettings.overridden = true;platformSettings.name = platform;// 设置为压缩platformSettings.textureCompression = TextureImporterCompression.Compressed;// 设置压缩格式platformSettings.format = format;                                    platformSettings.compressionQuality = compressionQuality;             platformSettings.maxTextureSize = GetMaxSize(texture as Texture2D);   //设置importSettingsTextureImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(texture)) as TextureImporter;importer.SetPlatformTextureSettings(platformSettings);//Apply 设置importer.SetPlatformTextureSettings(platformSettings);//保存资源importer.SaveAndReimport();count++;}//Debug.Log("Texture Compression Set!");}else{Debug.LogWarning("没有选中图片!");}Debug.Log($"一共处理了{count}张图片!");}/// <summary>/// 获取图片的分辨率,取分辨率中高宽的最大值,然后返回图片的【MaxSize】/// MaxSize的定义:assets->Image->【Texture2D ImportSettings】->【Override For WebGL】->【Max Size】 /// 区间:16,32,64,128,256,512,1024,2048,4096,8192,16384////// 举例:图片分辨率 = 12 * 24,那么图片的MaxSize = 32/// </summary>/// <param name="texture"></param>/// <returns></returns>static int GetMaxSize(Texture2D texture){//分辨率区间的预备var start = new List<int> { 0, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384 };var end = new List<int> { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 100000 };var zones = start.Zip(end, (item1, item2) => (startIdx: item1, endIdx: item2)).ToList();//取分辨率高宽的最大值var size = new List<int> { texture.width, texture.height }.Max();  //取【宽】【高】中的最大值//判断所属的区间var maxSize = zones.First(x => x.startIdx <= size && size <= x.endIdx).endIdx;//Debug.Log($"图的分辨率 = {texture.width} * {texture.height} size = {size}, MaxSize = {maxSize}");return maxSize;}
}

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

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

相关文章

基于SSM的教师信息管理系统

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于SSM的教师信息管理系统,java项目。 …

字符串原地旋转

记录一下做的练习题 字符串原地旋转&#xff1a;五 三 mat [[1,2,3],[3,4,5],[4,5,6]] tag0 total 0 for i in mat:total total i[tag]tag 1 print(total) 四 X [[12,7,3],[4,5,6],[7,8,9]] Y [[5,8,1],[6,7,3],[4,5,9]] res [[0,0,0],[0,0,0],[0,0,0]] for i in rang…

如何快速搭建一个大模型?简单的UI实现

&#x1f525;博客主页&#xff1a;真的睡不醒 &#x1f680;系列专栏&#xff1a;深度学习环境搭建、环境配置问题解决、自然语言处理、语音信号处理、项目开发 &#x1f498;每日语录&#xff1a;相信自己&#xff0c;一路风景一路歌&#xff0c;人生之美&#xff0c;正在于…

makefile编写练习

makefile编写练习 OVERVIEW makefile编写练习文件结构直接编译整个项目并运行将项目制作成为静态库将项目制作成为动态库 编写makefile文件来编译带头文件的程序&#xff0c; 文件结构 初始项目文件结构&#xff0c;如下所示&#xff1a; #ifndef ADD_HPP #define ADD_HPPint…

乘波前行的问题

1.问题&#xff1a; 考虑两个信号叠加在一起&#xff0c;比如&#xff0c;一个是工频信号50Hz&#xff0c;一个是叠加的高频信号比如有3KHz&#xff0c;简单起见&#xff0c;两个信号都是幅值固定的标准的正弦波&#xff0c;现在我们期望得到那个高频信号&#xff0c;相对工频…

Royal TSX v6.0.1

Royal TSX是一款基于插件的软件&#xff0c;适用于Windows系统&#xff0c;可以用于远程连接和管理服务器。它支持多种连接类型&#xff0c;如RDP、VNC、基于SSH连接的终端&#xff0c;SFTP/FTP/SCP或基于Web的连接管理。 在安装Royal TSX后&#xff0c;需要进行一些基础配置&…

如何停止输出“下载存储库‘rhel-8-for-x86_64-appstream-rpms’元数据时出错”错误?

问题 dnf[XXX]&#xff1a;下载存储库“rhel-8-for-x86_64-appstream-rpms”元数据时出错&#xff1a;如何禁用 dnf-makecache&#xff1f; 解决 离线系统无法下载元数据存储库&#xff0c;然后输出错误。 有两种方法可以阻止错误。 A) 在 /etc/dnf/dnf.conf 中添加以下行。…

C++中声明友元

C中声明友元 不能从外部访问类的私有数据成员和方法&#xff0c;但这条规则不适用于友元类和友元函数。要声明友元 类或友元函数&#xff0c;可使用关键字 friend&#xff0c;如以下示例程序所示&#xff1a; 使用关键字 friend 让外部函数 DisplayAge( )能够访问私有数据成员…

2023人形机器人行业海外科技研究:从谷歌看机器人大模型进展

今天分享的是人形机器人系列深度研究报告&#xff1a;《2023人形机器人行业海外科技研究&#xff1a;从谷歌看机器人大模型进展》。 &#xff08;报告出品方&#xff1a;华鑫证券&#xff09; 报告共计&#xff1a;26页 大模型是人形机器人的必备要素 长期来看&#xff0c;人…

openEuler 22.03 LTS x86_64 cephadm 部署ceph 16.2.14 未完成 笔记

环境 准备三台虚拟机 10.47.76.94 node-1 10.47.76.95 node-2 10.47.76.96 node-3 下载cephadm [rootnode-1 ~]# yum install cephadm Last metadata expiration check: 0:11:31 ago on Tue 21 Nov 2023 10:00:20 AM CST. Dependencies resolved. Package …

数据结构(超详细讲解!!)第二十五节 线索二叉树

1.线索二叉树的定义和结构 问题的提出&#xff1a; 通过遍历二叉树可得到结点的一个线性序列&#xff0c;在线性序列中&#xff0c;很容易求得某个结点的直接前驱和后继。但是在二叉树上只能找到结点的左孩子、右孩子&#xff0c;结点的前驱和后继只有在遍历过程中才能得到…

Python与设计模式--策略模式

12-Python与设计模式–策略模式 一、客户消息通知 假设某司维护着一些客户资料&#xff0c;需要在该司有新产品上市或者举行新活动时通知客户。现通知客户的方式有两 种&#xff1a;短信通知、邮件通知。应如何设计该系统的客户通知部分&#xff1f;为解决该问题&#xff0c;…

Alfred v5.1.4(mac快速启动)

Mac效率办公软件哪个好&#xff1f;Alfred是一款Mac电脑上的快速启动和工作流自动化工具&#xff0c;它可以帮助用户快速访问文件、应用程序、web搜索和系统工具&#xff0c;提高工作效率。以下是Alfred的特点&#xff1a; 快速启动&#xff1a;用户可以通过Alfred快速启动应用…

Node.js入门指南(四)

目录 express框架 express介绍 express使用 express路由 express 响应设置 中间件 路由模块化 EJS 模板引擎 express-generator hello&#xff0c;大家好&#xff01;上一篇文章我们介绍了Node.js的模块化以及包管理工具等知识&#xff0c;这篇文章主要给大家分享Nod…

Hive删除符合条件的记录

Hive在使用中不支持update和delete操作&#xff0c;那么如果想删除部分条件的记录需要怎么操作&#xff1f;本文记录下解决方法。 思路&#xff1a;使用selectwhere选出想要保留的数据&#xff0c;使用insert overwrite向原表覆盖插入数据. insert overwrite table dbname.tab…

车载通信架构 —— 传统车内通信网络MOST总线(光纤传输、专精多媒体)

车载通信架构 —— 传统车内通信网络MOST总线(光纤传输、专精多媒体) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都…

(2023码蹄杯)省赛(初赛)第三场真题(原题)(题解+AC代码)

题目1&#xff1a;MC0227堆煤球 码题集OJ-堆煤球 (matiji.net) 思路&#xff1a; 1.i从l枚举到r,i是8的倍数就跳过&#xff0c;i不是8的倍数就用等差数列求和公式i(1i)/2,最后累加到答案中即可 AC_Code:C #include<bits/stdc.h> using namespace std;int main( ) {in…

使用el-scrollbar实现定位滚动,以及el-scrollbar去掉横向滚动条

实现滚动 <el-scrollbar ref"scroll" style"height: 100%;">// ... </el-scrollbar>可以使用如下属性&#xff1a; this.$refs[scroll].wrap.scrollTop 0 //想滚到哪个高度&#xff0c;就写多少el-scrollbar去掉横向滚动条 ::v-deep .el-…

轻松实现文件按数量平均分类,高效整理并自动新建文件夹保存“

你是否曾经因为文件数量过多&#xff0c;整理起来繁琐而感到烦恼&#xff1f;是否曾经为了新建文件夹而手动一个一个进行创建&#xff0c;费时又费力&#xff1f;现在&#xff0c;我们的智能文件管理工具将为你解决这些问题&#xff01; 首先第一步&#xff0c;我们要进入文件…

【开源】基于Vue.js的网上药店系统

项目编号&#xff1a; S 062 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S062&#xff0c;文末获取源码。} 项目编号&#xff1a;S062&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 药品类型模块2.3 药…