Unity AssetPostProcessor资源导入规范自动化脚本(Presets)

1.AssetPostProcessor之OnPreprocess和OnPostprocess区别:

磁盘上的资源,并不是Unity使用的资源。在编辑器模式下,Unity会把我们放进去的外部资源Asset转换成一种Unity内部格式的资源,存储在Library/metadata路径下对应该Asset的GUID命名的文件,这个过程就是资源导入。

AssetPostProcessor是一个编辑器类,用来管理资源导入,当资源导入之前和之后都会发送通知,可以根据不同的资源类型,在导入之前和之后做不同的处理,来修改Untiy内部格式资源。一般我们通过这个类中OnPreprocess和OnPostprocess消息处理函数来修改资源数据和设置,这两者的区别可以简单理解为:

OnPreprocess用来改变资源报错在meta中的序列化信息,也就是说大部分是Inspector视图可见的选项。

OnPostprocess为导入过程中的一些处理,结果保存在最终的Library/metadata中,是和序列化无关的。

2.几个常用API:

//模型导入之前调用

public void OnPreprocessModel() { }

//模型导入之后调用
public void OnPostprocessModel(GameObject go){ }
 
 //Texture导入之前调用,针对Texture进行设置
public void OnPreprocessTexture() { }
 
//Texture导入之后调用,针对Texture进行设置
public void OnPostprocessTexture(Texture2D tex){}
 
//导入Audio后操作
public void OnPostprocessAudio(AudioClip clip) {}
     
 //导入Audio前操作
public void OnPreprocessAudio(){ }
 
//所有的资源的导入,删除,移动,都会调用此方法,注意,这个方法是static的
public static void OnPostprocessAllAssets(string[]importedAsset,string[] deletedAssets,string[] movedAssets,string[]movedFromAssetPaths)
{
        Debug.Log ("OnPostprocessAllAssets");
        foreach (string str in importedAsset) {
           Debug.Log("importedAsset = "+str);
        }
        foreach (string str in deletedAssets) {
            Debug.Log("deletedAssets = "+str);
        }
        foreach (string str in movedAssets) {
            Debug.Log("movedAssets = "+str);
        }
        foreach (string str in movedFromAssetPaths) {
            Debug.Log("movedFromAssetPaths = "+str);
        }
}

3.导入工具,自动化设置:

自动化优化导入的模型动画选项:

可以根据项目具体规划动态修改,需要放到Editor-scripts文件夹里面

using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class RigModelAutoImport : AssetPostprocessor {

    //美术资源路径
    //资源路径可以增加和修改,并在方法中添加if语句
    private static string modelRoot = "Assets/Model";
    private static string staticModelRoot = "Assets/Model/staticModel";
    private static string animationRoot = "Assets/Animation";

    //网格导入器, pre-process
    void OnPreprocessModel()
    {    
        //获得importer实例
        ModelImporter mImporter = assetImporter as ModelImporter;

        //——————————————模型部分
        //不要勾选Read/Write Enabled。我们使用特殊命名“_ReadWrite”无视这个规则,大家用目录来划分也可以
        mImporter.isReadable = mImporter.assetPath.Contains("_ReadWrite");

        //OptimizeMesh:顶点优化选项GPU性能可以得到提升
        mImporter.optimizeMesh = true;

        //其它不必要的数据导入关闭
        mImporter.importLights = false;
        mImporter.importCameras = false;


        //顶点包含Normals,不要Tangents。实际应用按照路径规划动态调整
        mImporter.importNormals = ModelImporterNormals.Import;
        mImporter.importTangents = ModelImporterTangents.None;

        //generateSecondaryUV第二套uv(光照UV)启用默认开启状态
        if (mImporter.assetPath.StartsWith(staticModelRoot))
        {
            //模型皆为静态时自动勾选静态
            //注意:模型静态勾选生成UV时间根据模型数据大小决定,开启此选项可能占用太多时间
            mImporter.generateSecondaryUV = true;
            mImporter.secondaryUVAngleDistortion = 8;
            mImporter.secondaryUVAreaDistortion = 15;
            mImporter.secondaryUVHardAngle = 88;
            mImporter.secondaryUVPackMargin = 4;
        }

        //关闭Material导入
        mImporter.importMaterials = false;
    }


    //网格和动画导入器, post-process
    void OnPostprocessModel(GameObject go) 
    {
        //获得importer实例
        ModelImporter mImporter = assetImporter as ModelImporter;

        //模型后处理部分
        if (mImporter.assetPath.StartsWith(modelRoot))
        {
            //自动去无用骨骼节点,例如后缀为"Nub"
            Transform[] transforms = go.GetComponentsInChildren<Transform> ();
            foreach(Transform t in transforms)
            {
                if(t.gameObject.name.EndsWith ("Nub"))
                {
                    GameObject.DestroyImmediate (t.gameObject);
                }
            }
        }

        //动画后处理部分
        if (mImporter.assetPath.StartsWith(animationRoot))
        {
            List<AnimationClip> animationClipList = new List<AnimationClip>(AnimationUtility.GetAnimationClips(go));
            if (animationClipList.Count == 0) {
                AnimationClip[] objectList = UnityEngine.Object.FindObjectsOfType (typeof(AnimationClip)) as AnimationClip[];
                animationClipList.AddRange(objectList);
            }
            
            foreach (AnimationClip theAnimation in animationClipList)
            {
                try 
                {
                    //如果文件命名没有包含_Scale,则去除scale曲线
                    if (!assetPath.Contains("_Scale"))
                    {
                        foreach (EditorCurveBinding theCurveBinding in AnimationUtility.GetCurveBindings(theAnimation))
                        {
                            string name = theCurveBinding.propertyName.ToLower();
                            if (name.Contains("scale"))
                            {
                                AnimationUtility.SetEditorCurve(theAnimation, theCurveBinding, null);
                            }
                        }
                    }

                    //浮点数精度压缩为f4
                    AnimationClipCurveData[] curves = null;
                    curves = AnimationUtility.GetAllCurves(theAnimation);
                    Keyframe key;
                    Keyframe[] keyFrames;
                    for (int ii = 0; ii < curves.Length; ++ii)
                    {
                        AnimationClipCurveData curveDate = curves[ii];
                        if (curveDate.curve == null || curveDate.curve.keys == null)
                        {
                            continue;
                        }
                        keyFrames = curveDate.curve.keys;
                        for (int i = 0; i < keyFrames.Length; i++)
                        {
                            key = keyFrames[i];
                            key.value = float.Parse(key.value.ToString("f4"));
                            key.inTangent = float.Parse(key.inTangent.ToString("f4"));
                            key.outTangent = float.Parse(key.outTangent.ToString("f4"));
                            keyFrames[i] = key;
                        }
                        curveDate.curve.keys = keyFrames;
                        theAnimation.SetCurve(curveDate.path, curveDate.type, curveDate.propertyName, curveDate.curve);
                    }
                }
                catch (System.Exception e)
                {
                    Debug.LogError(string.Format("CompressAnimationClip Failed! animationPath : {0} error: {1}", assetPath, e));
                }
            }
        }
    }
}

自动化优化导入的纹理选项:

using UnityEngine;
using UnityEditor;
using System.Text.RegularExpressions;
using System.IO;

public class TextureaAutoImport : AssetPostprocessor {

    //纹理导入器, pre-process
    void OnPreprocessTexture()
    {    
        //获得importer实例
        TextureImporter texImporter = assetImporter as TextureImporter;

        //设置Read/Write Enabled开关,不勾选
        texImporter.isReadable = false;    

        if (texImporter.assetPath.StartsWith("Assets/TexturesIsUI"))
        {
            //设置UI纹理Generate Mipmaps
            texImporter.mipmapEnabled = false;
            //设置UI纹理WrapMode
            texImporter.wrapMode = TextureWrapMode.Clamp;
        }

        //设置压缩格式,其它平台可根据规划在这里添加
        TextureImporterPlatformSettings psAndroid = texImporter.GetPlatformTextureSettings("Android");
        TextureImporterPlatformSettings psIPhone = texImporter.GetPlatformTextureSettings("iPhone");
        psAndroid.overridden = true;
        psIPhone.overridden = true;
        if (texImporter.DoesSourceTextureHaveAlpha())
        {
            psAndroid.format = TextureImporterFormat.ETC2_RGBA8;
            psIPhone.format = TextureImporterFormat.ASTC_RGBA_4x4;
        }
        else
        {
            psAndroid.format = TextureImporterFormat.ETC2_RGB4;
            psIPhone.format = TextureImporterFormat.ASTC_RGB_4x4;
        }
        texImporter.SetPlatformTextureSettings(psAndroid);
        texImporter.SetPlatformTextureSettings(psIPhone);
    }

}

猜你喜欢

转载自blog.csdn.net/Star_MengMeng/article/details/127532545
今日推荐