unity fbx动画按配置切割帧片段

主要参考该文章:人无两度s 《unity自动切割动画》 感谢作者分享

执行代码需要将模型与配置文件(.txt)放到同一目录下,批量选中模型后右键,代码中读取了选中的第一个模型同目录下可能存在的“动画帧分段.txt”,按其中的配置对选中的模型进行动画片段切分。

配置文件每行的格式:【帧数】,空格,【动画名】,空格,【模型1、模型2】
示例:
在这里插入图片描述
代码:

using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
using System.Collections.Generic;
using System.IO;
using System;
using System.Linq;

//txt文件,命名为"动画帧分段",与模型位于同一目录下,每行格式为[帧数(例如”100-200“),空格,动画名(xxxx),模型名(xx、xx)]
public class AniAutoCut : Editor
{
    public static Dictionary<string, List<AniCutConfig>> configs;
    public static string filePath;

    [MenuItem("Assets/一键切割动画")]
    public static void StartCutAni()
    {
        UnityEngine.Object[] objs = Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.Assets);
        configs = new();
        foreach (var obj in objs) 
        {
            Debug.Log(obj.name);
            configs[obj.name] = new List<AniCutConfig>();
        }
        ReadConfig(AssetDatabase.GetAssetPath(objs[0]));
        BatchCut();
    }

    private static void BatchCut()
    {
        foreach (KeyValuePair<string, List<AniCutConfig>> kvp in configs)
        {
            CutAni(filePath + kvp.Key + ".fbx", kvp.Value);
        }
    }

    private static void ReadConfig(string path)
    {
        //获取配置路径
        string[] tempPath = path.Split('/');
        filePath = "";
        foreach (string i in tempPath)
        {
            if (!i.Contains(".fbx"))
            {
                filePath += (i + "/");
            }
        }

        //数据处理
        if (File.Exists(filePath + "动画帧分段.txt"))
        {
            string file = File.ReadAllText(filePath + "动画帧分段.txt");

            if (file.Contains("\n"))
            {
                //拆分成行
                string[] arr = file.Split('\n');

                for (int i = 0; i < arr.Length; i++)
                {
                    if (!string.IsNullOrEmpty(arr[i]))
                    {
                        string[] item = arr[i].Split(" ", StringSplitOptions.RemoveEmptyEntries);

                        //标准格式行"XX XX XX"
                        if (item.Length == 3)
                        {
                            AniCutConfig acc = new();
                            acc.startFrame = int.Parse(item[0].Trim().Split("-")[0]);
                            acc.endFrame = int.Parse(item[0].Trim().Split("-")[1]);
                            acc.aniName = item[1].Trim();

                            string[] ModelNames = item[2].Split("、", StringSplitOptions.RemoveEmptyEntries);
                            
                            foreach (string ModelName in ModelNames)
                            {
                                if (configs.Keys.Contains(ModelName.Trim()))
                                {
                                    configs[ModelName.Trim()].Add(acc);
                                    //Debug.Log(ModelName + "   " + acc.startFrame + "  " + acc.endFrame + "  " + acc.aniName);
                                }
                            }
                        }
                    }
                }
            }
        }
        else
        {
            Debug.LogError("在动画路径下未找到\"动画帧分段.txt\"文件!");
        }
    }

    //传入模型路径与帧数列表
    private static void CutAni(string path, List<AniCutConfig> list)
    {
        ModelImporter model = AssetImporter.GetAtPath(path) as ModelImporter;
        List<ModelImporterClipAnimation> clipAnimations = new List<ModelImporterClipAnimation>();
        for (int i = 0; i < list.Count; i++)
        {
            ModelImporterClipAnimation clip = new ModelImporterClipAnimation();

            clip.name = list[i].aniName;
            clip.firstFrame = list[i].startFrame;
            clip.lastFrame = list[i].endFrame;
            //clip.loopPose = false;
            clipAnimations.Add(clip);
        }
        model.clipAnimations = clipAnimations.ToArray();
        model.SaveAndReimport();
        AssetDatabase.ImportAsset(path);
        AssetDatabase.Refresh();
    }
}

public class AniCutConfig
{
    public int startFrame;
    public int endFrame;
    public string aniName;
}

你可能感兴趣的:(unity)