zoukankan      html  css  js  c++  java
  • Unity3D批处理脚本

    Max09在模型到处的模型和U3D场景的尺寸不一致,Max09中的1m导到U3D中,只有0.01m,这时可以在U3D中将模型的FbxImporter中将Scale Factor改为1。

    上述事情也可以通过脚本直接处理:

    using UnityEditor;
    using UnityEngine;
    using System.Collections;

    public class FBXSeting : AssetPostprocessor
    {
    void OnPreprocessModel()
    {
    ModelImporter modelImporter = (ModelImporter)assetImporter;
    if(assetImporter.assetPath.Contains(".fbx"))
    {
    modelImporter.globalScale = 1.0f;
    modelImporter.generateMaterials = ModelImporterGenerateMaterials.None;
    }
    }
    }

    U3D有自动生成材质的功能(FbxImporter/Materials Generation,有3个选项可选),但我推荐使用脚本统一处理所有模型的材质。下面的代码抛砖引玉,通过菜单修改模型材质的颜色:

    using UnityEditor;
    using UnityEngine;
    using System.Collections;

    public class MaterialGeneration
    {
    [MenuItem("Actor/Generate Material")]
    static void Execute()
    {
    foreach (Object o in Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets))
    {
    if (!(o is GameObject)) continue;
    if (o.name.Contains("@")) continue;
    //if (!AssetDatabase.GetAssetPath(o).Contains("/characters/")) continue;

    GameObject charFbx = (GameObject)o;

    foreach (SkinnedMeshRenderer smr in charFbx.GetComponentsInChildren<SkinnedMeshRenderer>(true))
    {
    smr.material.color = Color.red;
    }
    }
    }
    }

    上面是处理人物材质的蒙皮网格的材质,对于场景模型,则改为修改MeshRenderer的数据。思路大致如此,细节以此类推。
    根据本人自己的经验,将modelImporter.generateMaterials设为PerMaterial(支持多重材质),然后批处理Fbx模型的Mesh,找到其材质,并修改之(包括修改Shader及Shader数据)。不建议删除现有材质,然后自己创建材质,并赋予给相应的Mesh,因为这种做法有个不好的地方:U3D重启后,材质关联丢失。而前面的方法,只是修改Mesh所关联材质的数据,后者是修改关联。

    思绪:

    U3D虽然降低了游戏编程门槛,不过定制功能真心强大,继续探索中......

    有些地方需要手动创建Prefab,可以通过以下代码实现代码批处理创建:

    Object tempPrefab = EditorUtility.CreateEmptyPrefab("Assets/" + name + ".prefab");

    tempPrefab = EditorUtility.ReplacePrefab(go, tempPrefab);

    通过脚本给模型prefab添加AnimationEvent:

    using UnityEditor;
    using UnityEngine;
    using System.IO;
    using System.Collections;
    using System.Collections.Generic;
    
    public class AnimationEventBatch
    {
        [MenuItem("Animation/AnimationEvent Batch")]
        static void Execute()
        {
            List<string> lstAnimName = new List<string>();
    
            foreach (Object o in Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets))
            {
                if (!(o is GameObject))
                    continue;
                if (o.name.Contains("@"))
                    continue;
                if (o.name.Contains("anim") || o.name.Contains("ANIM"))
                    continue;
                if (o.name.Contains("meta"))
                    continue;
                
                GameObject charFbx = (GameObject)o;
                
                AnimationClip[] clips = AnimationUtility.GetAnimationClips(charFbx.animation);
                
                foreach(AnimationClip clip in clips)
                {
                    if(clip.name.Contains("Take 0"))
                        continue;
                        
                    List<AnimationEvent> events = new List<AnimationEvent>(AnimationUtility.GetAnimationEvents(clip));
                    
                    if(HasStartEvent(events) && HasEndEvent(events))
                        continue;
                    
                    if(!HasStartEvent(events))
                    {
                        AnimationEvent startEvent = new AnimationEvent();
                        startEvent.time = 0.0005f;
                        startEvent.functionName = "StartCallBack";
                        events.Add(startEvent);
                    }
                    
                    if(!HasEndEvent(events))
                    {
                        AnimationEvent endEvent = new AnimationEvent();
                        endEvent.time = clip.length - 0.0005f;
                        endEvent.functionName = "EndCallBack";
                        events.Add(endEvent);
                    }
                    
                    AnimationUtility.SetAnimationEvents(clip, events.ToArray());
                }
                
                EditorUtility.DisplayDialog("fbxname", clips[0].name, "OK");
            }
        }
        
        static bool HasStartEvent(List<AnimationEvent> events)
        {
            foreach(AnimationEvent eventElem in events)
            {
                if(eventElem.functionName == "StartCallBack")
                    return true;
            }
            return false;
        }
        
        static bool HasEndEvent(List<AnimationEvent> events)
        {
            foreach(AnimationEvent eventElem in events)
            {
                if(eventElem.functionName == "EndCallBack")
                    return true;
            }
            return false;
        }
    }

    上述代码仅供参考,代码中有几个注意事项:

    (1)一定要在现有AnimationEvent[]数组的基础上添加,而不是新建一个这样的数组,然后Set给对应的AnimationClip,这样会导致现有的关键帧事件丢失;

    (2)要避免重复添加同意关键帧事件(貌似u3d对于同样时间同样函数名的关键帧只会添加一次);

    (3)可以看到,在添加关键帧事件时,只需要给出函数的名字,那么,在此动作执行时,U3D会检查这个GameObject身上的所有组件脚本,如果组件A包含此名字的函数,则会执行此函数。并且所有组件的此名字的函数都会执行一次。

    批量设置图片的格式:

    public class GuideUITextureProcess 
    {
        [MenuItem("Editor/Texture/GuideUITexture")]
        static void Execute()
        {
            foreach (Object o in Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets))
            {
                if (!(o is Texture))
                    continue;
    
                Texture tex = o as Texture;
                string path = AssetDatabase.GetAssetPath(tex);
                TextureImporter textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;
                textureImporter.textureType = TextureImporterType.GUI;
                AssetDatabase.ImportAsset(path);
            }
            AssetDatabase.Refresh();
        }
    }

       Prefab.Apply操作的回调:

    using UnityEngine;
    using UnityEditor;
    
    [InitializeOnLoad]
    public class PrefabExtension : MonoBehaviour
    {
        static PrefabExtension()
        {
            UnityEditor.PrefabUtility.prefabInstanceUpdated += OnPrefabInstanceUpdate;
        }
    
        static void OnPrefabInstanceUpdate(GameObject instance)
        {
            UnityEngine.Debug.Log("[Callback] Prefab.Apply on instance named :" + instance.name);
    
            GameObject prefab = UnityEditor.PrefabUtility.GetPrefabParent(instance) as GameObject;
            string prefabPath = AssetDatabase.GetAssetPath(prefab);
            UnityEngine.Debug.Log("@Prefab originPath=" + prefabPath);
        }
    }


    继续探索中......



  • 相关阅读:
    邻接矩阵
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
  • 原文地址:https://www.cnblogs.com/sifenkesi/p/2373755.html
Copyright © 2011-2022 走看看