まるコットでメモ的な何か

FBXからAnimationを抜き出して既存のAnimationClipアセットに上書きするエディタ拡張

Unity 2021.3.6

概要

Blender等の3DCGソフトでモデルのアニメーションを更新したあと、Unityに持っていく時に毎回以下の作業を実施している。

  1. UnityのAssetフォルダ配下のFBXファイルを直接上書き保存
  2. UnityのProjectパネルからFBXを開き、アニメーションを選択してCTRL + Dで抜き出し
  3. ファイルエクスプローラ等から操作して既存のAnimationClipに上書き保存

問題点として、3の操作をした際に既存のAnimationClipに設定したLoopやAnimationEventなどの情報が消えてしまう。
(結構な問題だと思うけど、言及してる人がほとんど居ないのは何故…)

この問題を解消するためにFBX内のアニメーションのCurve情報のみ既存のAnimationClipに上書きして保存するエディタ拡張を作った。

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

public class FBXAnimExtractor
{
	static string exportAnimFolder = "Animations";

	[MenuItem("Assets/Extract FBX Animations")]
	static void AssetCopy() {
		Object[] selectedAssets = Selection.GetFiltered(typeof(Object), SelectionMode.Assets);
		foreach (var asset in selectedAssets) {
			ExtractFunc(asset);
		}

		AssetDatabase.Refresh();
		Debug.Log("FBXAnimExtractor Done.");
	}

	private static void ExtractFunc(Object obj) {
		string path = AssetDatabase.GetAssetPath(obj);
		string exportFolder = Path.Combine(Path.GetDirectoryName(path), exportAnimFolder);

		if(!Directory.Exists( exportFolder )){
            Directory.CreateDirectory( exportFolder );
        }

		var fbx = AssetDatabase.LoadAllAssetsAtPath(path);
		var originalClips = System.Array.FindAll<Object>(fbx, item =>
			  item is AnimationClip
		);

		foreach(var clip in originalClips) {
			copyClip(clip, exportFolder);
		}
	}

	private static void copyClip(Object clip, string exportFolder) {
		if (clip.name.StartsWith("__preview__"))
			return;

		var instance = Object.Instantiate(clip);
		AnimationClip newAnim = instance as AnimationClip;

		string clip_name = clip.name.Replace("|", "_") + ".anim"; // replace illegal character
		string exportPath = Path.Combine(exportFolder, clip_name);

		if(File.Exists(exportPath)){
			var actions = new List<System.Action>();
			var bindings = AnimationUtility.GetCurveBindings(newAnim);
			AnimationClip existingAnim = (AnimationClip)AssetDatabase.LoadAssetAtPath(
					exportPath, typeof(AnimationClip));

			foreach (var binding in bindings)
			{
				var curve = AnimationUtility.GetEditorCurve(newAnim, binding);
				var cb = binding;
			
				actions.Add(() =>
				{
					AnimationUtility.SetEditorCurve(existingAnim, cb, curve);
				});
			}

			existingAnim.ClearCurves();
			foreach (var action in actions)
    			action.Invoke();

			AssetDatabase.SaveAssets();
		}else{
			AssetDatabase.CreateAsset(newAnim, exportPath);
		}
	}
}

使い方

  1. Assets配下にEditorという名前のフォルダを作成(ビルド時に使用されない特殊なフォルダー名
  2. UnityのProjectパネルから右クリック>Create>C# Scriptを選択してFBXAnimExtractorという名前のスクリプトファイルをEditorフォルダに作成
  3. 上記のコードをFBXAnimExtractorファイルにコピペして保存
  4. アニメーションを抜き出したいFBXを複数選択して右クリック>Extract FBX Animationsを選択

すると、FBXがあるフォルダ配下にAnimationsというフォルダが作られてその中にAnimationClipが新規作成または上書き保存されます。

参考にしたサイト

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です