Unity材质清理器
本文介绍一种快捷清理Unity材质球上关联的废弃贴图引用的方法,全程无痛方便,推荐大家在自己项目中做一次全局清理。
材质球的无用贴图残留是这样产生的:
第一步,创建一个带有多张贴图材质球资源
第二步,直接切换成一个使用更少贴图数量的shader,看上去这个材质球似乎清理了多余的贴图引用,但是实际上它这个机制隐藏了资源引用
第三步,选择材质球资源,点击Select Dependencies,显示所有依赖,果然原有的两张贴图资源还被引用着
由上面的重现步骤来看,我们日常的美术制作流程是非常容易引入上述的冗余问题的,材质球shader的切换,并不会清理掉多余贴图槽位上的资源引用,导致资源被冗余包含到发布包中,白白浪费内存,浪费加载带宽。
所以我们就非常有必要对项目中的所有材质文件做一次全局大扫除,达到优化资源的目的。我们仅仅需要一个简单的批处理脚本,该脚本会清理掉材质球上所有没有被shader引用到的贴图资源引用。
下面给出核心代码,使用了一个小技巧来保证材质资源引用正确,希望对大家有用
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System;
using UnityEngine;
using UnityEditor;static class MaterialCleaner {public static bool ClearMaterialAsset( Material m ) {if ( m == null ) {return false;}var path = AssetDatabase.GetAssetPath( m );if ( String.IsNullOrEmpty( path ) ) {return false;}var deps = AssetDatabase.GetDependencies( new String[] { path } );var deps_textures = deps.Where( s => IsTextureAsset( s ) ).ToList();var used_textures = new HashSet<String>();var shader = m.shader;var newMat = new Material( shader );var c = ShaderUtil.GetPropertyCount( shader );for ( int i = 0; i < c; ++i ) {var type = ShaderUtil.GetPropertyType( shader, i );var name = ShaderUtil.GetPropertyName( shader, i );var value = m.GetProperty( i );switch ( type ) {case ShaderUtil.ShaderPropertyType.Color: {newMat.SetColor( name, m.GetColor( name ) );}break;case ShaderUtil.ShaderPropertyType.Float: {newMat.SetFloat( name, m.GetFloat( name ) );}break;case ShaderUtil.ShaderPropertyType.Range: {newMat.SetFloat( name, ( float )value );}break;case ShaderUtil.ShaderPropertyType.TexEnv: {newMat.SetTexture( name, ( Texture )value );newMat.SetTextureOffset( name, m.GetTextureOffset( name ) );newMat.SetTextureScale( name, m.GetTextureScale( name ) );var tpath = AssetDatabase.GetAssetPath( ( Texture )value );if ( !String.IsNullOrEmpty( tpath ) ) {used_textures.Add( tpath );}}break;case ShaderUtil.ShaderPropertyType.Vector: {newMat.SetVector( name, ( Vector4 )value );}break;}}bool rebuild = false;if ( used_textures.Count != deps_textures.Count ) {for ( int i = 0; i < deps_textures.Count; ++i ) {var _fn = deps_textures[ i ];if ( !used_textures.Contains( _fn ) ) {rebuild = true;UnityEngine.Debug.LogWarning( String.Format( "unused texture: {0}", _fn ) );}}}if ( !rebuild ) {if ( newMat != null ) {UnityEngine.Object.DestroyImmediate( newMat );}return false;}String basePath;String fn;String ext;SplitFullFilename( path, out fn, out ext, out basePath );var tempAssetPath = String.Format( "{0}{1}_temp.{2}", basePath, fn, ext );var _test = AssetDatabase.LoadAllAssetsAtPath( tempAssetPath );if ( _test != null ) {AssetDatabase.DeleteAsset( tempAssetPath );}// create a new material to replace it latterAssetDatabase.CreateAsset( newMat, tempAssetPath );Resources.UnloadAsset( newMat );var tempAssetDataPath = String.Format( "{0}{1}_datatemp.bytes", basePath, fn, ext );if ( File.Exists( tempAssetPath ) ) {// rename it to .bytesFile.Copy( tempAssetPath, tempAssetDataPath, true );// delete temp materialAssetDatabase.DeleteAsset( tempAssetPath );if ( File.Exists( tempAssetDataPath ) ) {// delete original materialFile.Delete( path );// replace original material with .bytes fileFile.Copy( tempAssetDataPath, path, true );// remove bytes fileFile.Delete( tempAssetDataPath );AssetDatabase.Refresh();// make sure the temp file has been removed correctlyif ( File.Exists( tempAssetDataPath ) ) {UnityEngine.Debug.Log( String.Format( "AssetDatabase.DeleteAsset failed: {0}", tempAssetDataPath ) );File.Delete( tempAssetDataPath );AssetDatabase.Refresh();return true;}}}return false;}static void SplitFilename( String qualifiedName, out String outBasename, out String outPath ) {String path = qualifiedName.Replace( '\\', '/' );int i = path.LastIndexOf( '/' );if ( i == -1 ) {outPath = String.Empty;outBasename = qualifiedName;} else {outBasename = path.Substring( i + 1, path.Length - i - 1 );outPath = path.Substring( 0, i + 1 );}}static void SplitBaseFilename( String fullName, out String outBasename, out String outExtention ) {int i = fullName.LastIndexOf( '.' );if ( i == -1 ) {outExtention = String.Empty;outBasename = fullName;} else {outExtention = fullName.Substring( i + 1 );outBasename = fullName.Substring( 0, i );}}static void SplitFullFilename( String qualifiedName, out String outBasename, out String outExtention, out String outPath ) {String fullName = String.Empty;SplitFilename( qualifiedName, out fullName, out outPath );SplitBaseFilename( fullName, out outBasename, out outExtention );}static object GetProperty( this Material material, int index ) {var name = ShaderUtil.GetPropertyName( material.shader, index );var type = ShaderUtil.GetPropertyType( material.shader, index );switch ( type ) {case ShaderUtil.ShaderPropertyType.Color:return material.GetColor( name );case ShaderUtil.ShaderPropertyType.Vector:return material.GetVector( name );case ShaderUtil.ShaderPropertyType.Range:case ShaderUtil.ShaderPropertyType.Float:return material.GetFloat( name );case ShaderUtil.ShaderPropertyType.TexEnv:return material.GetTexture( name );}return null;}static bool IsTextureAsset( String assetPath ) {var ext = Path.GetExtension( assetPath ).ToLower();return ext == ".png" ||ext == ".tga" ||ext == ".jpg" ||ext == ".bmp" ||ext == ".psd" ||ext == ".dds" ||ext == ".exr";}
}
Unity材质清理器相关推荐
- Unity开发备忘录000006:用Unity标准着色器构建金属材质效果(二)
按照Unity开发备忘录000005:用Unity标准着色器构建金属材质效果(一)所介绍的方法,我们又做了一个如下的模型渲染. 在此基础上我们再给它加一个高度贴图,其立体感的细节会更加丰富,如下图: ...
- Unity Shader着色器优化
对游戏开发者而言,着色器长久以来就是游戏开发中的重要部分,在Unity中编写并实现着色器的过程直观且高效,优秀的着色器还可以创造非常精美的游戏画面,同时保证极高的性能.今天将由Unity的技术工程师张 ...
- unity材质球发光_Unity Lighting - Emissive Materials 自发光材质(九)
Whilst Area Lights are not supported by Precomputed Realtime GI, similar soft lighting effects are s ...
- Unity材质球个人学习笔记
Unity材质球个人学习笔记 Shader FX: Lighting and glass effects.( 灯光.玻璃) GUI and UI: For user interface graphic ...
- Unity API-----Renderer(渲染器)
Unity API-----Renderer(渲染器) 官方文档阅读记录 版本 : 2019.3 官方文档传送门 Renderer是UnityEngine命名空间下的一个类. Renderer继承于C ...
- UE4材质着色器全面学习教程
你会学到什么 通过所有着色器类型和设计的实际演示,学习创建材质 要求 对虚幻的基本理解会有所帮助 了解纹理的一般知识(不仅限于UE4)也很有用 描述 在这个系列中,我将带你设置大量不同的材料,教你如何 ...
- 学习编写Unity计算着色器 Learn to Write Unity Compute Shaders
利用图形处理器的力量 你会学到: 如何编写Unity计算着色器 如何在后处理图像过滤器中使用ComputeShaders 如何使用ComputeShaders进行粒子效果和群集 如何使用Structu ...
- 系统垃圾文件清理器 制作:China Doll (莫增成)
@echo off ::修正于2018-10-06 color 4a Title 系统垃圾文件清理器 制作:China Doll (莫增成) echo. echo ================== ...
- Unity车轮碰撞器起步刹车太慢
Unity车轮碰撞器起步刹车太慢 遇到的问题 尝试的办法 刹车慢 起步慢 遇到的问题 在学校学习<物理引擎>专业课的时候,我们的期末作业是用unity的WheelCollider组件来对汽 ...
最新文章
- 高德纳咨询公司(Gartner)预测:2019年七大人工智能科技趋势
- PHP知识点 自己做个记录
- ios 点击出现另外一套tabbar_iOS开发中TabBar再次点击实现刷新效果
- deepin执行apt-get update报错https://deb.opera.com/opera-stable stable Release” 没有 Release 文件N: 无法安全地用该
- java编译后生成字节码_请问java源文件编译后怎么生成字节码文件?
- 基础知识(十三)dlib python人脸检测 特征点定位
- 操作系统(13)-操作系统中的死锁及其预防、避免、检测与解除
- python中psum是什么意思_python中**是什么
- 解决firefox和IE9对icon font字体的跨域访问问题
- CentOS下双网卡绑定-bond0
- centos7阿里yum源报问题
- java 调用百度语音
- 【JZOJ4587】Snow的追寻 题解
- 宁夏大学计算机科学与技术排名,2016宁夏自治区大学各学科门类最佳专业排行榜...
- 论文中文翻译——Vulnerability Dataset Construction Methods Applied To Vulnerability Detection A Survey
- Linux应用程序利用libudev库识别USB设备
- iOS 应用内购买基础教程 swift篇
- 安装webpack及使用
- 西电李航 操作系统课程笔记 day11 IO softwarelayer
- 一般测试测几轮?每轮测什么?
热门文章
- 电源电路中电感为什么会啸叫?
- Java开发环境!杭州java开发应届生工资
- centos系统删除多余网卡的方法
- 阿里云发送短信代码、C++版
- java计算机毕业设计慧学IT精品课程网站源码+mysql数据库+系统+lw文档+部署
- 【java基础】为什么重写toString()方法?
- 【看完这篇就够了!!!通俗易懂】置信度理解(95%的置信度、置信区间)
- 请自己写出strcpy函数
- python更新织梦网站_织梦DEDECMS自动更新首页的办法
- 解决支付宝小程序微信小程序post请求后台接收不到参数的问题