提取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);
}
}
}