资源工作流之自动导出FBX动画

此工具用途:
美术给出模型,自动导出 animator 和 animation(避免一直ctrl+D出来)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Text;
using UnityEditor.Animations;

public class ModelAnimationEditor
{

    [MenuItem("Tools/模型/AutoExport FBX Animation")]
    private static void AutoExport()
    {
        string[] strs = Selection.assetGUIDs;
        string dir = AssetDatabase.GUIDToAssetPath(strs[0]);

        if (!IsValid(dir))
        {
            Debug.LogError("请选择正确的文件夹。");
        }
        else
        {
            Debug.Log("开始导出 path: " + dir);
            ExportByPath(dir);
        }
        AssetDatabase.SaveAssets();
    }

    public static void ExportByPath(string dir)
    {
        Reset(dir);
        CreateAnimationClips(dir);
        CreateAnimationController(dir);
    }

    static bool IsValid(string path)
    {
        return !string.IsNullOrEmpty(path) && Directory.Exists(path) && Directory.Exists(path + "/fbx");
    }

    static string outputDir = string.Empty;
    static List<AnimationClip> animationClips = new List<AnimationClip>();

    static void Reset(string path)
    {
        animationClips.Clear();
        outputDir = path + "/output/";
        if (Directory.Exists(outputDir))
        {
            Directory.Delete(outputDir, true);
        }
        Directory.CreateDirectory(outputDir);
    }

    static void CreateAnimationClips(string path)
    {
        string fbxDir = path + "/fbx/";
        DirectoryInfo fbxDirInfo = Directory.CreateDirectory(fbxDir);
        FileInfo[] fbxFiles = fbxDirInfo.GetFiles("*.fbx", SearchOption.AllDirectories);
        foreach (var fbxFile in fbxFiles)
        {
            var fbxName = fbxFile.Name;
            int index = fbxName.IndexOf("@");
            if (index == -1)
                continue;
            
            string nameWithEx = fbxFile.Name.Substring(index + 1);
            string onlyName = nameWithEx.Substring(0, nameWithEx.IndexOf("."));
            
            if (onlyName =="fall"
                ||onlyName =="throw"
                ||onlyName =="stun"
                ||onlyName =="spells"
                ||onlyName =="skill3"
                ||onlyName =="skill4"
                ||onlyName =="skill5"
                ||onlyName =="skill6"
                ||onlyName =="skill7"
                ||onlyName =="skill10"
                ||onlyName =="skill14"
                ||onlyName =="skill17"
                ||onlyName =="skill20"
                ||onlyName =="ui"
                )
                continue;

            if (fbxName.StartsWith("mc"))
            {
                if (onlyName == "skill2"
                    ||onlyName =="ax_hit"
                    ||onlyName =="ax_spells"
                    ||onlyName =="gun_hit"
                    ||onlyName =="gun_spells"
                    ||onlyName =="sepea_hit"
                    ||onlyName =="sepea_spells"
                    ||onlyName =="attack2"
                    ||onlyName =="ax_attack2"
                    ||onlyName =="sepea_attack2"
                )
                    continue; 
            }
            
            string name =  onlyName+ ".anim";
            string assetPath = fbxFile.FullName.Substring(fbxFile.FullName.IndexOf("Assets"));
            
            List<AnimationClip> animationClipList = GetAllAnimationClip(assetPath);
            foreach (var clip in animationClipList)
            {
                AnimationClip newClip = CopyAnimationClip(clip);
                animationClips.Add(newClip);
            }
        }
    }

    static void CreateAnimationController(string path)
    {
        string folderName = path.Substring(path.LastIndexOf('/') + 1);
        string outputPath = outputDir + folderName + ".controller";
        UnityEditor.Animations.AnimatorController animatorController = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerAtPath(outputPath);
        UnityEditor.Animations.AnimatorControllerLayer layer = animatorController.layers[0];
        UnityEditor.Animations.AnimatorStateMachine machine = layer.stateMachine;

        foreach (var clip in animationClips)
        {
            AnimatorState state = machine.AddState(clip.name);
            state.motion = clip;

            if (state.name == "idle")
            {
                machine.defaultState = state;
            }
        }

        AssetDatabase.Refresh();
    }


    #region 多动画拷贝
    private static List<AnimationClip> GetAllAnimationClip(string assetPath)
    {
        List<AnimationClip> animationClipList = new List<AnimationClip>();
        UnityEngine.Object[] clips = AssetDatabase.LoadAllAssetsAtPath(assetPath);
        foreach (var one in clips)
        {
            if (one.GetType() != typeof(AnimationClip))
            {
                continue;
            }
            //根动画不参与
            if (one.name.Contains("__preview__"))
            {
                continue;
            }
            AnimationClip newClip = one as AnimationClip;
            animationClipList.Add(newClip);

        }
        return animationClipList;
    }

    private static AnimationClip CopyAnimationClip(AnimationClip sourceClip)
    {
        AnimationClip temp = new AnimationClip();
        EditorUtility.CopySerialized(sourceClip, temp);

        if (temp.name.EndsWith("idle") || temp.name.EndsWith("run") || temp.name.EndsWith("stun") || temp.name.Contains("ui_"))
        {
            AnimationClipSettings clipSetting = AnimationUtility.GetAnimationClipSettings(temp);
            clipSetting.loopTime = true;
            AnimationUtility.SetAnimationClipSettings(temp, clipSetting);
        }

        string outputPath = outputDir + sourceClip.name + ".anim";
        AssetDatabase.CreateAsset(temp, outputPath);
        return temp;
    }
    #endregion
}

上一篇:读取FBX文件踩坑清单


下一篇:SAP WM LI04 试图去打印一个已经完成盘点流程(清账)的盘点单, 系统会报错!