Unity引擎材质球残留贴图引用的处理
大家好,我是阿赵。
这次来分享一下Unity引擎材质球残留贴图引用的处理
一、 问题
在使用Unity调整美术效果的时候,我们很经常会有这样的操作,比如:
1、 同一个材质球切换不同的Shader、
比如我现在有2个Shader,其中第一个Shader的参数是这样的:
Properties{_MainTex ("MainTex", 2D) = "white" {}_MaskTex("MaskTex",2D) = "black" {}_floatVal("FloatVal",float) = 1_rangeVal("RangeVal",Range(0,1)) = 1_vecVal ("VectorVal",Vector) = (1,1,1,1)_colVal ("ColorVal",Color) = (1,1,1,1)}
而第二个Shader的参数是这样的:
Properties{_MainTex ("MainTex", 2D) = "white" {}_specTex("SpecTex",2D) = "black" {}_floatVal("FloatVal",float) = 1_rangeVal("RangeVal",Range(0,1)) = 1_vecVal ("VectorVal",Vector) = (1,1,1,1)_colVal ("ColorVal",Color) = (1,1,1,1)}
可以看出,它们两个的参数几乎一样,区别只是在一张贴图的名称不同。
假如先在材质球里选第一个Shader,并且把两个贴图的赋上,现在材质球是这样:

然后在这个材质球里面,把Shader改成第二个Shader,会变成这样:

很明显,第二张贴图由于名字不一样,所以这个Shader上不会显示之前的那张贴图。
这时候疑问来了,换了Shader之后,之前的贴图通道里面的引用,是不是就不用管了呢?

这时候,可以打开Debug来看这个材质球的参数:

可以看到,刚才使用在上一个Shader里面的贴图_MaskTex,其实还是保存在引用里面的。这说明一个问题,假如我们给一个材质球替换Shader,其实上一个Shader使用而当前Shader没有使用的字段参数,都保存在材质球的引用里面。如果我们继续使用这个材质球,那么打包资源的时候很可能就会带着一张我们根本没有用到的贴图。
2、 同一个Shader修改参数的名称
还是拿第一个Shader作为例子:
Properties{_MainTex ("MainTex", 2D) = "white" {}_MaskTex("MaskTex",2D) = "black" {}_floatVal("FloatVal",float) = 1_rangeVal("RangeVal",Range(0,1)) = 1_vecVal ("VectorVal",Vector) = (1,1,1,1)_colVal ("ColorVal",Color) = (1,1,1,1)}

还是把上面的2张贴图都赋上。
  这时候,假如我修改一下其中一张贴图的变量名
Properties{_MainTex ("MainTex", 2D) = "white" {}_MaskTex2("MaskTex",2D) = "black" {}_floatVal("FloatVal",float) = 1_rangeVal("RangeVal",Range(0,1)) = 1_vecVal ("VectorVal",Vector) = (1,1,1,1)_colVal ("ColorVal",Color) = (1,1,1,1)}
我把_MaskTex改成了_MaskTex2。

这个时候,会发现之前赋予的_MaskTex贴图消失不见了。
这时候问题又来了。是不是修改了Shader里面的变量声明,那么之前声明的变量引用的贴图就消失了呢?
同样的打开Debug模式看:

虽然新增了_MaskTex2的保存项,但实际上原来的_MaskTex贴图还是存在的,引用的贴图也依然存在。所以同样的道理,如果这个时候我们继续使用这个材质球,那么打包的时候,就会包含了一张我们已经不用了的贴图。
通过上面2个例子可以说明,其实材质球上面已经保存过的参数,不论材质球当前的Shader是否有声明变量,都会在Saved Properties里面一直存在着。但如果不用Debug模式去观察,可能很多使用Unity的朋友都不知道这个问题的存在。这可以说是Unity引擎设计上的一个缺陷。一般使用Unity进行美术资源编辑的,都是美工同事们,他们一般都不会去使用Debug模式,而正常模式下的材质球属性显示里面又没有任何的提示,所以虽然包含了多余的美术资源,但他们是很难发现的。
二、 解决问题。
如果我们通过材质球的Reset选项去清空材质球的所有参数

当然是可以把不用的贴图给清理掉。但那样做的话,会顺便把其他我们正常使用的属性也清理掉了。这显然不是我们想要达到的目的。
我们的目的很简单,就是保留现在的Shader用到的参数,去掉已经不需要的参数。Unity似乎没有直接提供这样的手段,起码阿赵我没有找到。不过我们可以通过另外一种迂回一点的手段,去实现这个目的。
思路是这样的:
1、 获得材质球当前使用的Shader的所有属性名称
通过
ShaderUtil.GetPropertyCount(shader);
可以获得当前Shader声明的变量个数
2、 使用当前Shader创建一个新的临时材质球
Material newMat = new Material(shader);
3、 通过遍历所有属性名称,从旧的材质球上面获取对应的变量参数,然后赋予给新的临时材质球。
由于不同的变量需要用不同的方法获取和赋值,所以需要知道每一个变量的类型,通过
ShaderUtil.ShaderPropertyType propType = ShaderUtil.GetPropertyType(shader,i);
可以获得变量类型

类型只有5种,所以根据类型分别去操作就行了。Range和Float其实是一样的,用GetFloat和SetFloat方法获取就行。
4、 通过复制材质球属性,把临时材质球的所有属性赋予给原来的材质球。
通过方法:
mat.CopyPropertiesFromMaterial(newMat);
可以把临时材质球的所有属性复制给原来的材质球。
5、 最后保存一下原来的材质球
通过这些手段之后,目的达到了,不使用的变量被清空,需要的变量保留下来。

通过这个思路,可以写一个批处理的工具,批量清理材质球。
三、 源码
根据自己的情况,写一个UnityEditor的工具,然后遍历需要的材质球,传入方法:
private void CleanUnusedProp(Material mat)
{if(mat == null){return;}//获得当前材质球使用的ShaderShader shader = mat.shader;//创建一个临时的材质球Material newMat = new Material(shader);//获得Shader声明的变量的数量int propCount = ShaderUtil.GetPropertyCount(shader);for(int i = 0;i<propCount;i++){//获得变量的类型ShaderUtil.ShaderPropertyType propType = ShaderUtil.GetPropertyType(shader,i);//获得变量的名称string propName = ShaderUtil.GetPropertyName(shader, i);//根据变量类型赋值switch(propType){case ShaderUtil.ShaderPropertyType.Float:newMat.SetFloat(propName, mat.GetFloat(propName));break;case ShaderUtil.ShaderPropertyType.Range:newMat.SetFloat(propName, mat.GetFloat(propName));break;case ShaderUtil.ShaderPropertyType.Vector:newMat.SetVector(propName, mat.GetVector(propName));break;case ShaderUtil.ShaderPropertyType.Color:newMat.SetColor(propName, mat.GetColor(propName));break;case ShaderUtil.ShaderPropertyType.TexEnv:newMat.SetTexture(propName, mat.GetTexture(propName));break; }}//复制材质球参数mat.CopyPropertiesFromMaterial(newMat);//保存材质球EditorUtility.SetDirty(mat);AssetDatabase.SaveAssets();AssetDatabase.Refresh();
}
相关文章:
Unity引擎材质球残留贴图引用的处理
大家好,我是阿赵。 这次来分享一下Unity引擎材质球残留贴图引用的处理 一、 问题 在使用Unity调整美术效果的时候,我们很经常会有这样的操作,比如: 1、 同一个材质球切换不同的Shader、 比如我现在有2个Shader,…...
Flutter鸿蒙next中封装一个列表组件
1. 创建Flutter项目 首先,确保你已经安装了Flutter SDK,并创建一个新的Flutter项目: flutter create podcast_app cd podcast_app2. 封装列表组件 我们将在lib目录下创建一个新的文件,命名为podcast_list.dart,用于…...
层次与网络的视觉对话:树图与力引导布局的双剑合璧
目录 目的内容树图绘制目的步骤参考代码结果与分析 力引导布局算法目的参考代码结果与分析 总结 目的 掌握常用可视化软件与工具:学习和熟练使用常用的数据可视化软件和工具,如Matplotlib、Seaborn、Plotly、Tableau等。这些工具提供了用于创建图表、图…...
python将数据集中所有文件名升序制作txt文件(医学影像)
import os import re # 设定图像文件所在的路径 img_path ./2d/images/ #需修改路径 # 获取该路径下的所有文件名 img_list os.listdir(img_path) # 过滤出以.nii结尾的文件名 nii_list [f for f in img_list if f.endswith(.nii)] # 使用正则表达式从文件名中提…...
【The Art of Unit Testing 3_自学笔记06】3.4 + 3.5 单元测试核心技能之:函数式注入与模块化注入的解决方案简介
文章目录 3.4 函数式依赖注入技术 Functional injection techniques3.5 模块化依赖注入技术 Modular injection techniques 写在前面 上一篇的最后部分对第三章后续内容做了一个概括性的梳理,并给出了断开依赖项的最简单的实现方案,函数参数值注入法。本…...
【VSCode】配置
安装插件 C vscode-icons gdb调试 https://www.bilibili.com/video/BV15U4y1x7b2/?spm_id_from333.999.0.0&vd_sourcedf0ce73d9b9b61e6d4771898f1441f7f https://www.bilibili.com/video/BV1pU4y1W74Z?spm_id_from333.788.recommend_more_video.-1&vd_sourcedf0…...
Linux 常用命令整理大全及命令使用心得
本文章是为了总结自己用过的命令,以及一些心得,网上有很多类似的,但自己总结才能更好的理解。 文章目录 一、文件和目录管理01、 ls :列出目录内容02、cd:更改当前目录03、pwd:显示当前工作目录04、mkdir&a…...
计算器的实现
计算器的⼀般实现 计算器的一般实现:优化:使⽤函数指针数组的实现: 计算器的一般实现: #include <stdio.h> int add(int a, int b) {return a b; } int sub(int a, int b) {return a - b; } int mul(int a, int b) {retur…...
这个工具帮你快速实现数据集成和同步
在这个信息爆炸的时代,数据的流动和同步逐渐成为企业运营的命脉。然而,企业正面临着前所未有的数据挑战,无论是跨地域的分公司协作,还是云服务与本地数据库的交互,数据的集成、清洗、转换和加载(ETL&#x…...
论文阅读:Computational Long Exposure Mobile Photography (一)
这篇文章是谷歌发表在 2023 ACM transaction on Graphic 上的一篇文章,介绍如何在手机摄影中实现长曝光的一些拍摄效果。 Abstract 长曝光摄影能拍出令人惊叹的影像,用运动模糊来呈现场景中的移动元素。它通常有两种模式,分别产生前景模糊或…...
项目解决方案:多地连锁药店高清视频监控系统建设解决方案(设计方案)
目录 一.项目背景 1.1背景描述 1.2需求分析 二.设计依据和建设目标 2.1设计依据 2.2建设目标 三.系统设计实现 3.1系统方案设计 3.2网络组网说明 四.建设系统特色 4.1安全性 4.2节约建设成本 4.3原有资源的再利用 4.4可扩展性 五.产品介绍 5.1概述 5.2设备…...
utf-8、pbkdf2_sha
#utf-8加密、解密 import base64 base64.b64encode(lienlien123.encode(utf-8)) bbGllbmxpZW4xMjM base64.b64decode(bbGllbmxpZW4xMjM.decode(utf-8)) blienlien123 #pbkdf2_sha加密,校验 # 该种密码在不同时刻会有产生不同的加密结果 # 该加密方法使用的是散列…...
Java之包,抽象类,接口
目录 包 导入包 静态导入 将类放入包 常见的系统包 抽象类 语法规则 注意事项: 抽象类的作用 接口 实现多个接口 接口间的继承 接口使用实例 (法一)实现Comparable接口的compareTo()方法 (法二)实现Comp…...
HarmonyOS鸿蒙开发入门,常用ArkUI组件学习(二)
书接上回,让我们继续来学习ArkUI的其他组件 目录,可以点击跳转到想要了解的组件详细内容 组件四:Button组件五:Slider组件六: Column & Row组件七:循环控制组件八: List 组件四:…...
斩!JavaScript语法进阶
一、DOM 概述 DOM 是 JavaScript 操作网页的接口,全称为“文档对象模型”(Document Object Model)。当网页被加载时,浏览器将网页转为一个DOM,并用JS进行各种操作。比如:改变页面中的HTML 元素及其属性&am…...
UFO:Windows操作系统的具象智能代理
近年来,随着AI技术的发展,智能代理在各种应用中扮演着越来越重要的角色。微软推出的UFO(User-Focused Operator)正是这样一个出色的多代理框架,旨在通过无缝导航和操作,满足用户在Windows操作系统中跨多个应…...
win10/11无休眠设置和断电后电池模式自动休眠而不是睡眠-用以省电
1、打开休眠设置选项 打开控制面板\所有控制面板项\电源选项\ 左侧的选择电源按钮的功能 默认状态没有休眠 1、管理员权限打开cmd或者power shell 2、输入一下指令,打开休眠选项 powercfg -hibernate on关闭后重新打开 控制面板\所有控制面板项\电源选项\左侧的选…...
【动态规划之斐波那契数列模型】——累加递推型动态规划
文章目录 第N个泰波那契数列面试题08.01.三步问题使用最小花费爬楼梯解码问题 第N个泰波那契数列 解题思路: 泰波那契数列的第 N 项定义为前面三项之和,即 T0 0, T1 1, T2 1,从 T3 开始,每一项都等于前三项的和。要找到第 N 项…...
5g通信系统用到的crc码
5g通信系统用到的crc码 关注 在5G通信系统中,CRC码(循环冗余校验码)扮演着关键角色,它通过执行多项式除法运算来检测数据在传输过程中是否发生错误。5G通信系统中采用了多种CRC码,每种码都有其独特的计算方法和校验特…...
Ubuntu-22.04 虚拟机安装
1. Ubuntu安装方式 1.1. 基于物理介质安装 光盘安装:通过将 Ubuntu 镜像刻录到光盘,在计算机 BIOS/UEFI 中设置光盘为第一启动项,然后按照安装程序的提示进行语言选择、分区、用户信息设置等操作来完成安装。这种方式需要有光盘刻录设备和空…...
TV Bro电视浏览器:如何在Android电视上享受完整网页浏览体验的终极指南
TV Bro电视浏览器:如何在Android电视上享受完整网页浏览体验的终极指南 【免费下载链接】tv-bro Simple web browser for android optimized to use with TV remote 项目地址: https://gitcode.com/gh_mirrors/tv/tv-bro 您是否曾经尝试在智能电视上浏览网页…...
立体仓库WMS深度解析
立体仓库WMS深度解析📌 封面语:立体仓库失败案例中,80% 不是硬件问题,而是 WMS 和 WCS “对话” 失败。想避坑,先搞懂这套软件怎么运转。 ✍️ 作者:这是「物流自动化软件内参」WMS 深度解析系列的第一篇。…...
大语言模型本地化部署利器:Synaptic-Link 模型文件管理工具详解
1. 项目概述与核心价值最近在折腾一些AI相关的本地化部署和模型管理,发现一个挺有意思的项目,叫dlxeva/synaptic-link。乍一看这个名字,可能有点摸不着头脑,“突触链接”?听起来像是神经科学或者生物信息学的东西。但如…...
数字卡尺原理深度解析:从电容传感技术到精密测量实践
1. 数字卡尺:从机械指针到电容传感的进化在车间、实验室或者任何一个需要和精确尺寸打交道的角落,卡尺都是工程师、技师和创客们最忠实可靠的伙伴。过去,我们依赖的是表盘上跳动的指针,或者游标卡尺上需要仔细对齐的刻度线&#x…...
Dot自定义配置指南:调整模型参数满足个性化需求
Dot自定义配置指南:调整模型参数满足个性化需求 【免费下载链接】Dot Text-To-Speech, RAG, and LLMs. All local! 项目地址: https://gitcode.com/gh_mirrors/dot1/Dot Dot是一款功能强大的本地AI应用,支持文本转语音、RAG(检索增强生…...
ARM PMU中断控制寄存器PMINTENCLR/PMINTENSET详解
1. ARM性能监控单元(PMU)架构概述 在现代处理器设计中,性能监控单元(Performance Monitoring Unit, PMU)是实现系统级性能分析和优化的关键组件。ARM架构从v7开始引入标准化的PMU设计,并在v8/v9架构中持续演进。PMU的核心功能是通过一组可编程事件计数器…...
Clawless框架:构建合规网页数据抓取系统的设计哲学与实践指南
1. 项目概述与核心价值最近在GitHub上闲逛,发现了一个名为“Clawless”的项目,作者是HainanZhao。这个项目名挺有意思,“Clawless”直译是“无爪”,听起来像是一个温和无害的工具。点进去一看,发现它是一个用于自动化处…...
ARM Cortex-M处理器仿真与Iris组件深度解析
1. ARM Cortex-M系列处理器仿真技术概述在嵌入式系统开发领域,处理器仿真技术已经成为不可或缺的工具链环节。作为ARM架构中专门面向微控制器市场的产品线,Cortex-M系列处理器凭借其优异的能效比和实时性能,广泛应用于物联网终端、工业控制和…...
开源安全工具openclaw-killer:Nginx Lua环境威胁检测与防护实践
1. 项目概述:一个开源安全工具的诞生与使命最近在安全研究圈子里,一个名为openclaw-killer的项目引起了我的注意。这个由nkzprod维护的开源工具,名字就透着一股“杀气”——“OpenClaw杀手”。乍一看,你可能会以为这是某个游戏外挂…...
普通人 0 基础能转网安吗?转行路径全面拆解,告诉你到底值不值得
前言 最近在后台有看到很多朋友问我关于网络安全转行的问题,今天做了一些总结,其中最多的是,觉得目前的工作活多钱少、不稳定、一眼望到头,还有一些就是目前工作稳定但是缺乏上升空间的。总的来说,大家主要的问题是&a…...
