资源工作流之自动导出FBX动画
2020-09-09 本文已影响0人
APP4x
此工具用途:
美术给出模型,自动导出 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
}