当前位置: 首页 > ops >正文

【7.5 Unity AssetPostprocessor】

7.5 Unity AssetPostprocessor 介绍

AssetPostprocessor 是 Unity 资源管道的核心扩展点,它提供了一系列回调方法,允许开发者在资源导入流程的不同阶段插入自定义逻辑。这些回调方法构成了强大的资源处理框架,下面是关键回调方法表:

AssetPostprocessor 回调方法详解)

方法签名触发时机参数说明核心作用
void OnPreprocessAsset()在导入任何类型资产之前通用预处理入口,可获取 assetPath
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)批量资产操作(导入/删除/移动)完成后importedAssets:新导入资产
deletedAssets:已删除资产
movedAssets:移动后路径
movedFromAssetPaths:移动前路径
全局后处理(依赖管理/资源索引更新)
void OnPreprocessAnimation()导入独立 .anim 文件配置 AnimationClip 导入设置
void OnPostprocessAnimation(GameObject root, AnimationClip clip)从模型文件(如FBX)导入动画root:模型根对象
clip:导入的动画片段
处理嵌入模型的动画
void OnPreprocessTexture()导入纹理(PNG/JPG等)配置 TextureImporter(压缩格式/mipmap)
void OnPostprocessTexture(Texture2D texture)纹理导入完成后texture:生成的纹理对象纹理后处理(质量检查/生成衍生图)
void OnPreprocessModel()导入3D模型(FBX/OBJ)配置 ModelImporter(缩放/动画类型/优化)
void OnPostprocessModel(GameObject root)模型导入完成后root:模型根对象模型后处理(添加碰撞体/生成LOD)
void OnPreprocessAudio()导入音频(WAV/MP3)配置 AudioImporter(压缩格式/加载类型)
void OnPostprocessAudio(AudioClip audioClip)音频导入完成后audioClip:生成的音频对象音频后处理(音量标准化/频谱分析)
void OnPreprocessMaterialDescription()从模型导入材质(Unity 2018.3+)修改材质描述(Shader/纹理分配)
void OnPostprocessMaterial(Material material)材质导入完成后material:生成的材质对象材质后处理(属性调整/关键字添加)
void OnPostprocessSprites(Texture2D texture, Sprite[] sprites)精灵图集导入完成后texture:图集纹理
sprites:生成的精灵数组
精灵后处理(Pivot设置/碰撞体生成)
void OnPostprocessPrefab(GameObject prefabRoot)预制体(Prefab)导入完成后prefabRoot:预制体根对象预制体后处理(组件检查/引用设置)
void OnPostprocessCubemap(Cubemap cubemap)立方体贴图导入完成后cubemap:生成的立方体贴图立方体贴图后处理
void OnPostprocessGameObjectWithUserProperties(GameObject root, string[] propNames, object[] values)导入包含自定义属性的模型root:根对象
propNames:属性名数组
values:属性值数组
处理模型中的静态自定义属性(如元数据)
void OnPostprocessGameObjectWithAnimatedUserProperties(GameObject root, AnimationClip clip, EditorCurveBinding[] properties)导入包含动画自定义属性的模型root:根对象
clip:动画片段
properties:动画属性绑定
处理模型中的动画自定义属性
void OnPostprocessMeshHierarchy(GameObject root)模型层级导入完成后root:模型根对象最终层级处理(添加全局组件/清理空对象)

关键说明:

  1. 位置: 包含这些回调方法的脚本必须放在项目的 Assets/Editor 文件夹(或其子文件夹)中才能生效。
  2. assetImporterassetPath 在非静态的实例方法中,基类 AssetPostprocessor 提供了 assetImporter (当前导入器对象) 和 assetPath (当前资产路径) 属性,用于获取关键信息。
  3. 类型特定导入器: 在预处理方法中,可以将 assetImporter 转换为具体的导入器类型(如 TextureImporter, ModelImporter, AudioImporter)来访问和修改特定于该类型资产的导入设置。
  4. OnPostprocessAllAssets 这是唯一的静态回调方法,用于处理批量操作后的逻辑。
  5. 触发时机: “预处理”方法在 Unity 实际执行导入操作之前调用,允许修改导入设置。“后处理”方法在 Unity 完成导入并创建了 Unity 内部对象(如 Texture2D, GameObject, AudioClip之后调用,允许修改这些对象或执行基于它们的逻辑。
  6. 避免循环导入: 在后处理方法中修改资产或其元数据可能导致 Unity 重新导入该资产,形成循环。需谨慎处理或使用标志位避免。

这个表格提供了 AssetPostprocessor 主要回调方法的概览及其作用。开发者可以根据项目需求选择实现特定的回调方法来定制资源导入流程。

举个栗子,这是书本上的一个例子,主要纹理导入的例子,手动对纹理一个一个导入,费时费力,我们可以通过使用ScriptsableObjcet,制作导入设置,通过设置批量操作。

第一步, ScriptableObject 实现了一个可配置的纹理预处理系统
代码如下

using System.IO;
using UnityEngine;
using UnityEditor;// 在Unity的Asset创建菜单中添加选项,用于创建此配置资源
[CreateAssetMenu]
public class TexturePreprocessSettings : ScriptableObject
{// ==============================// 纹理基础设置// ==============================// 纹理类型(默认、法线贴图、精灵等)[SerializeField] private TextureImporterType textureType = TextureImporterType.Default;// 纹理形状(2D、立方体贴图等)[SerializeField] private TextureImporterShape textureShape = TextureImporterShape.Texture2D;// 是否为sRGB颜色空间(颜色纹理应为true,非颜色纹理如法线贴图应为false)[SerializeField] private bool sRGBTexture = true;// Alpha通道来源(从输入获取、无Alpha等)[SerializeField] private TextureImporterAlphaSource alphaSource = TextureImporterAlphaSource.FromInput;// Alpha通道是否表示透明度[SerializeField] private bool alphaIsTransparency;// 是否忽略PNG文件的Gamma值[SerializeField] private bool ignorePNGFileGamma;// ==============================// 高级设置// ==============================// 标题分组[Header("Advanced")]// 非2的幂次方纹理缩放处理方式[SerializeField] private TextureImporterNPOTScale nonPowerOf2= TextureImporterNPOTScale.ToNearest;// 是否启用读写访问(会增加内存使用)[SerializeField] private bool readWriteEnabled;// 是否启用Mipmap流式加载(减少内存占用)[SerializeField] private bool streamingMipmaps;// 是否仅用于虚拟纹理(需要Unity的虚拟纹理系统)[SerializeField] private bool vitrualTextureOnly;// 是否生成Mipmap(多级渐远纹理)[SerializeField] private bool generateMipMaps = true;// Mipmap是否使用边框[SerializeField] private bool borderMipMaps;// Mipmap过滤算法[SerializeField] private TextureImporterMipFilter mipmapFilter= TextureImporterMipFilter.BoxFilter;// Mipmap是否保留覆盖范围(用于Alpha测试)[SerializeField] private bool mipMapsPreserveCoverage;// Mipmap是否启用淡出效果[SerializeField] private bool fadeoutMipMaps;// ==============================// 纹理采样设置// ==============================// 纹理环绕模式(重复、夹取等)[SerializeField] private TextureWrapMode wrapMode= TextureWrapMode.Repeat;// 纹理过滤模式(点过滤、双线性、三线性)[SerializeField] private FilterMode filterMode = FilterMode.Bilinear;// 各向异性过滤级别(0-16)[SerializeField, Range(0, 16)] private int anisoLevel = 1;// ==============================// 压缩与尺寸设置// ==============================// 纹理最大尺寸(长宽最大值)[SerializeField] private int maxSize = 2048;// 纹理格式(自动、RGBA32等)[SerializeField] private TextureImporterFormat format= TextureImporterFormat.Automatic;// 压缩方式(无压缩、压缩等)[SerializeField] private TextureImporterCompression compression= TextureImporterCompression.Compressed;// 是否使用Crunch压缩(高压缩比的有损压缩)[SerializeField] private bool useCrunchCompression;// ==============================// 单例访问器实现// ==============================// 静态实例引用private static TexturePreprocessSettings m_Settings;// 单例访问器属性private static TexturePreprocessSettings Settings{get{// 如果实例未加载if (m_Settings == null){// 配置资源的标准路径var path = "Assets/Settings/" +"Texture Preprocess Settings.asset";// 尝试从AssetDatabase加载配置m_Settings = AssetDatabase.LoadAssetAtPath<TexturePreprocessSettings>(path);// 如果资源不存在,创建新实例if (m_Settings == null){// 创建新的ScriptableObject实例m_Settings = CreateInstance<TexturePreprocessSettings>();// 确保Settings目录存在var directory = Application.dataPath + "/Settings";if (!Directory.Exists(directory))Directory.CreateDirectory(Application.dataPath + "/Settings");// 创建资产并刷新数据库AssetDatabase.CreateAsset(m_Settings, path);AssetDatabase.Refresh();}}return m_Settings;}}// ==============================// 公共静态访问器// 提供对私有字段的安全访问// ==============================// 基础设置访问器public static TextureImporterType TextureType => Settings.textureType;public static TextureImporterShape TextureShape => Settings.textureShape;public static bool SRGBTexture => Settings.sRGBTexture;public static TextureImporterAlphaSource AlphaSource => Settings.alphaSource;public static bool AlphaIsTransparency => Settings.alphaIsTransparency;public static bool IgnorePNGFileGamma => Settings.ignorePNGFileGamma;// 高级设置访问器public static TextureImporterNPOTScale NonPowerOf2 => Settings.nonPowerOf2;public static bool ReadWriteEnabled => Settings.readWriteEnabled;public static bool StreamingMipmaps => Settings.streamingMipmaps;public static bool VitrualTextureOnly => Settings.vitrualTextureOnly;public static bool GenerateMipMaps => Settings.generateMipMaps;public static bool BorderMipMaps => Settings.borderMipMaps;public static TextureImporterMipFilter MipmapFilter => Settings.mipmapFilter;public static bool MipMapsPreserveCoverage => Settings.mipMapsPreserveCoverage;public static bool FadeoutMipMaps => Settings.fadeoutMipMaps;// 采样设置访问器public static TextureWrapMode WrapMode => Settings.wrapMode;public static FilterMode FilterMode => Settings.filterMode;public static int AnisoLevel => Settings.anisoLevel;// 压缩设置访问器public static int MaxSize => Settings.maxSize;public static TextureImporterFormat Format => Settings.format;public static TextureImporterCompression Compression => Settings.compression;public static bool UseCrunchCompression => Settings.useCrunchCompression;
}

在这里插入图片描述
第二步,使用第一步创建好的设置,代码如下
在这里插入图片描述

using UnityEngine;
using UnityEditor;// 纹理后处理器类,继承自Unity的AssetPostprocessor
public class TexturePostprocessor : AssetPostprocessor
{// 在纹理导入前调用的方法private void OnPreprocessTexture(){// 将当前资源导入器转换为纹理导入器TextureImporter importer = assetImporter as TextureImporter;// 如果转换失败(即当前导入的不是纹理),直接返回if (importer == null)return;// =============================================// 应用全局纹理预处理设置// =============================================// 设置纹理形状(2D、Cube等)importer.textureShape = TexturePreprocessSettings.TextureShape;// 设置是否为sRGB颜色空间importer.sRGBTexture = TexturePreprocessSettings.SRGBTexture;// 设置Alpha通道来源importer.alphaSource = TexturePreprocessSettings.AlphaSource;// 设置Alpha通道是否表示透明度importer.alphaIsTransparency = TexturePreprocessSettings.AlphaIsTransparency;// 设置是否忽略PNG文件的Gamma值importer.ignorePngGamma = TexturePreprocessSettings.IgnorePNGFileGamma;// 设置非2的幂次方纹理的缩放处理方式importer.npotScale = TexturePreprocessSettings.NonPowerOf2;// 设置是否启用CPU读写访问(会增加内存占用)importer.isReadable = TexturePreprocessSettings.ReadWriteEnabled;// 设置是否启用Mipmap流式加载importer.streamingMipmaps = TexturePreprocessSettings.StreamingMipmaps;// 设置是否仅用于虚拟纹理importer.vtOnly = TexturePreprocessSettings.VitrualTextureOnly;// 设置是否生成Mipmapimporter.mipmapEnabled = TexturePreprocessSettings.GenerateMipMaps;// 设置Mipmap是否使用边框importer.borderMipmap = TexturePreprocessSettings.BorderMipMaps;// 设置Mipmap过滤算法importer.mipmapFilter = TexturePreprocessSettings.MipmapFilter;// 设置Mipmap是否保留覆盖范围importer.mipMapsPreserveCoverage = TexturePreprocessSettings.MipMapsPreserveCoverage;// 设置Mipmap是否启用淡出效果importer.fadeout = TexturePreprocessSettings.FadeoutMipMaps;// 设置纹理环绕模式importer.wrapMode = TexturePreprocessSettings.WrapMode;// 设置纹理过滤模式importer.filterMode = TexturePreprocessSettings.FilterMode;// 设置各向异性过滤级别importer.anisoLevel = TexturePreprocessSettings.AnisoLevel;// 设置纹理最大尺寸importer.maxTextureSize = TexturePreprocessSettings.MaxSize;// 设置纹理压缩方式importer.textureCompression = TexturePreprocessSettings.Compression;// 设置是否使用Crunch压缩importer.crunchedCompression = TexturePreprocessSettings.UseCrunchCompression;// 设置纹理类型(Default、NormalMap、Sprite等)importer.textureType = TexturePreprocessSettings.TextureType;}// =============================================// 模型导入后处理方法(当前为空实现)// =============================================/// <summary>/// 在导入带有用户自定义属性的模型后调用/// </summary>/// <param name="gameObject">导入的模型根对象</param>/// <param name="propNames">属性名称数组</param>/// <param name="values">属性值数组</param>private void OnPostprocessGameObjectWithUserProperties(GameObject gameObject,string[] propNames,object[] values){// 可在此处添加处理自定义属性的逻辑// 例如根据属性自动添加组件或设置参数}// =============================================// 模型层级后处理方法(当前为空实现)// =============================================/// <summary>/// 在模型层级导入完成后调用/// </summary>/// <param name="root">模型根对象</param>private void OnPostprocessMeshHierarchy(GameObject root){// 可在此处添加处理模型层级的逻辑// 例如优化层级结构、添加LOD组件等}
}

这个时候就会发现所有的Texture就会被设置为上图那样,不要在实际项目中测试,这个脚本没撤回功能。

http://www.xdnf.cn/news/16877.html

相关文章:

  • 【自动化运维神器Ansible】YAML支持的数据类型详解:构建高效Playbook的基石
  • linux ext4缩容home,扩容根目录
  • Trae + Notion MCP:将你的Notion数据库升级为智能对话机器人
  • 元宇宙重构未来交通新图景
  • 无人机光伏巡检漏检率↓78%!陌讯多模态融合算法实战解析
  • 机试备考笔记 2/31
  • Agentic RAG:自主检索增强生成的范式演进与技术突破
  • 深入 Go 底层原理(二):Channel 的实现剖析
  • 深入 Go 底层原理(十四):timer 的实现与高性能定时器
  • cuda编程笔记(12)--学习cuFFT的简单使用
  • 【机器学习】非线性分类算法(上):KNN(基于距离相似度)与朴素(特征独立)贝叶斯(基于概率统计)
  • Lock 接口及实现类详解:从 ReentrantLock 到并发场景实践
  • Node.js 操作 MongoDB
  • 【LeetCode 热题 100】739. 每日温度——(解法一)单调栈+从右到左
  • 最新Windows11系统镜像,23H2 64位ISO镜像
  • 拉格朗日插值法
  • 【软考中级网络工程师】知识点之堆叠
  • MySQL PostgreSQL JDBC URL 配置允许批量操作
  • 系统思考:超越线性分析
  • openwrt下安装istore(基于pve)
  • Linux网络编程【基于UDP网络通信的字典翻译服务】
  • Effective C++ 条款17:以独立语句将newed对象置入智能指针
  • 农田通量计算方法与应用;高精度感热/潜热通量反演与绘图等;农田蒸散发与能量平衡
  • 50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | QuizApp(交互式在线测验应用组件)
  • Mujoco(MuJoCo,全称Multi - Joint dynamics with Contact)一种高性能的物理引擎
  • 基于Postman进行http的请求和响应
  • linux基本系统服务——DNS服务
  • 【嵌入式汇编基础】-ARM架构基础(三)
  • 宝塔配置文件缺失导致无法正常启动
  • Java 集合框架: LinkedHashSet