提取Unity中的fbx文件中的动画片段。

提取Unity中的fbx文件中的动画片段。

整体思路是:

将fbx加载后,获取AnimationClip信息,然后序列滑到新文件中。

// 生成新的AnimationClip

                        AnimationClip newClip = new AnimationClip();

                        newClip.frameRate = 25;

                        newClip.name = objs[j].name;

                        // 复制数据

                        // 方法1:该方法仅设置有效数据,编辑器相关数据不会设置到导出资源中

                        EditorUtility.CopySerialized(objs[j], newClip);


直接上代码:

public class AnimationExporter : AssetBaseExporter { public class FbxInfo { public string m_AssetPath; public string m_AssetName; // 资源名 public bool m_IsExport; // 是否导出 public bool m_IsCompress; //是否压缩 } string m_AssetPathPrefix = "Assets/Resources/Models"; // 资源路径前缀(所有需要导出动画的fbx以该目录为根目录,不同的模型可以在该目录下新建子目录) string m_AssetExportPathPrefix = "Assets/Resources/Pack/Ani"; Listm_AssetList; bool m_IsCompress = true; bool m_IsSelectAll = true; Vector2 m_ScrollPos = Vector2.zero; protected override string m_AssetFilter { get { return "t:model"; } } public override string m_ActionResultFileName { get { return "AnimExportResult.txt"; } } public override void Init() { m_ExportResultDict = new Dictionary(); } public override void Draw() { if (m_AssetList == null) { GUI.contentColor = Color.red; EditorGUILayout.TextArea("请选择资源目录或者某个导出资源"); GUI.contentColor = Color.white; return; } if (GUILayout.Button("一键全选/一键取消全选", GUILayout.Height(50))) { m_IsSelectAll = !m_IsSelectAll; for (int idx = 0; idx < m_AssetList.Count; ++idx) { FbxInfo fbxInfo = m_AssetList[idx]; fbxInfo.m_IsExport = m_IsSelectAll; fbxInfo.m_IsCompress = m_IsSelectAll; } } m_ScrollPos = EditorGUILayout.BeginScrollView(m_ScrollPos, false, false); for (int idx = 0; idx < m_AssetList.Count; ++idx) { FbxInfo fbxInfo = m_AssetList[idx]; fbxInfo.m_IsExport = EditorGUILayout.BeginToggleGroup("勾选", fbxInfo.m_IsExport); // 组开始 EditorGUILayout.TextField(fbxInfo.m_AssetName,GUILayout.Width(500)); EditorGUILayout.EndToggleGroup(); // 组结束 fbxInfo.m_IsCompress = EditorGUILayout.BeginToggleGroup("勾选", fbxInfo.m_IsCompress); // 组开始 EditorGUILayout.TextField("是否压缩", GUILayout.Width(500)); EditorGUILayout.EndToggleGroup(); // 组结束 } EditorGUILayout.EndScrollView(); } public override void PreAction() { base.PreAction(); AnimationModelCompresser.GetInstance().Init(); CompressAnimationExcludeInfoMgr.GetInstance().Init(); } public override void DoAction(string resPath, bool isPath) { if (isPath) { for (int idx = 0; idx < m_AssetList.Count; ++idx) { if (m_AssetList[idx].m_IsExport) { m_IsCompress = m_AssetList[idx].m_IsCompress; DoAction(m_AssetList[idx].m_AssetPath); } } AssetDatabase.Refresh(); } else { base.DoAction(resPath, isPath); } } protected override void DoAction(string assetPath) { if (!assetPath.Contains(m_AssetPathPrefix)) return; Object obj = AssetDatabase.LoadAssetAtPath(assetPath, typeof(GameObject)); if (obj == null) return; if (PrefabUtility.GetPrefabType(obj) == PrefabType.ModelPrefab) { // 创建导出目录 string exportPath = assetPath.Replace(m_AssetPathPrefix, m_AssetExportPathPrefix); exportPath = Application.dataPath.Replace("Assets", exportPath); exportPath = exportPath.Substring(0, exportPath.LastIndexOf("/") + 1); EditorBasePanel.CheckTargetPath(exportPath); GameObject gameObj = GameObject.Instantiate(obj) as GameObject; if (gameObj.GetComponent() == null) { GameObject.DestroyImmediate(gameObj); return; } gameObj.GetComponent().clip = null; if (m_IsCompress) { DictionaryerrorDic = new Dictionary(); AnimationModelCompresser.IsCollectErrorInfo = true; if (AnimationModelCompresser.GetInstance().CompressAnimationModel(assetPath, out errorDic) && errorDic.Count > 0) { // 排序 List> lst = new List>(errorDic); lst.Sort(delegate(KeyValuePairs1, KeyValuePairs2) { return s2.Value.CompareTo(s1.Value); }); foreach (KeyValuePairerrorPair in lst) { SaveAsClips(assetPath, errorPair.Value, errorPair.Key, gameObj, exportPath); } float minError = Mathf.Infinity; foreach (KeyValuePairpair in errorDic) { minError = Mathf.Min(minError, pair.Value); } errorDic.Clear(); // 设置回原来的 ImportSettingsHelper.SetImportSettingsCompressionError(assetPath, minError); } else { SaveAsClips(assetPath, 0, string.Empty, gameObj, exportPath); } } else { SaveAsClips(assetPath, 0, string.Empty, gameObj, exportPath); } // 导出prefab string prefabPath = exportPath.Replace(Application.dataPath, "Assets") + obj.name + ".prefab"; //PrefabUtility.CreatePrefab(prefabPath, gameObj); GameObject.DestroyImmediate(gameObj); } EditorUtility.UnloadUnusedAssets(); } void SaveAsClips(string assetPath, float errorValue, string clipName, GameObject gameObj, string exportPath) { if (errorValue > 0) { ImportSettingsHelper.SetImportSettingsCompressionError(assetPath, errorValue); } Object[] objs = AssetDatabase.LoadAllAssetsAtPath(assetPath); for (int j = 0; j < objs.Length; ++j) { if ((objs[j].GetType()) == typeof(AnimationClip)) { if (string.IsNullOrEmpty(clipName) || objs[j].name == clipName) { //UnityEngine.Debug.Log(objs[j].name); AnimationState state = gameObj.GetComponent()[objs[j].name]; if (state == null) continue; // 生成新的AnimationClip AnimationClip newClip = new AnimationClip(); newClip.frameRate = 25; newClip.name = objs[j].name; // 复制数据 // 方法1:该方法仅设置有效数据,编辑器相关数据不会设置到导出资源中 EditorUtility.CopySerialized(objs[j], newClip); // 方法2:该方法会将编辑器相关数据设置到导出资源中 /* EditorCurveBinding[] bindings = AnimationUtility.GetCurveBindings(objs[j] as AnimationClip); for (int bindIdx = 0; bindIdx < bindings.Length; ++bindIdx) { AnimationCurve curve = AnimationUtility.GetEditorCurve(objs[j] as AnimationClip, bindings[bindIdx]); AnimationUtility.SetEditorCurve(newClip, bindings[bindIdx], curve); } // * */ /* // 方法3:该方法会将编辑器相关数据设置到导出资源中 AnimationClipCurveData[] curveDatas = AnimationUtility.GetAllCurves(objs[j] as AnimationClip, true); for (int curIdx = 0; curIdx < curveDatas.Length; ++curIdx) { AnimationClipCurveData curve = curveDatas[curIdx]; AnimationUtility.SetEditorCurve(newClip, curve.path, curve.type, curve.propertyName, curve.curve); } * */ // 导出动画 string animPath = exportPath.Replace(Application.dataPath, "Assets") + objs[j].name + ".anim"; AssetDatabase.CreateAsset(newClip, animPath); string resultPath = animPath.Replace(m_AssetExportPathPrefix, "Resources/Pack/Ani"); resultPath = resultPath.Replace(".anim", ""); AddActionResult(assetPath, resultPath); // 移除动画 gameObj.GetComponent().RemoveClip(objs[j].name); } } } } public override void OnSelectPath(string path, bool isPath) { if (isPath) { m_AssetList = new List(); path = path.Replace(Application.dataPath, "Assets"); string[] assets = AssetDatabase.FindAssets(m_AssetFilter, new string[] { path }); if (assets != null) { for (int idx = 0; idx < assets.Length; ++idx) { string assetPath = AssetDatabase.GUIDToAssetPath(assets[idx]); FbxInfo fbxInfo = new FbxInfo(); fbxInfo.m_AssetPath = assetPath; fbxInfo.m_AssetName = Path.GetFileName(assetPath); fbxInfo.m_IsExport = true; fbxInfo.m_IsCompress = true; m_AssetList.Add(fbxInfo); } } } else { path = path.Replace(Application.dataPath, "Assets"); path = path.Substring(0, path.LastIndexOf("/")); m_AssetList = new List();

                FbxInfo fbxInfo = new FbxInfo();

                fbxInfo.m_AssetPath = path;

                fbxInfo.m_AssetName = Path.GetFileName(path);

                fbxInfo.m_IsExport = true;

                fbxInfo.m_IsCompress = true;

                m_AssetList.Add(fbxInfo);

            }

        }

    }

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,366评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,521评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,689评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,925评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,942评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,727评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,447评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,349评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,820评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,990评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,127评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,812评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,471评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,017评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,142评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,388评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,066评论 2 355

推荐阅读更多精彩内容