2023/9/2 追記
proxy_tpose のアニメーションに上書きする場合は、以下の記事を参照してほしい。
BlendShape と proxy_tpose からアニメーションを生成する
VRChat アバターで使用するために、BlendShape から1フレームのループアニメーションを生成したい。
スクリプト
using System.IO;
using UnityEditor;
using UnityEngine;
public class GenerateAnimationFromBlendShape : MonoBehaviour
{
//Assetsフォルダのアバターを変数にセットしてもらう
public GameObject avatar;
[ContextMenu("GenerateAnimationFromBlendShape")]
public void GenerateAnimFromBlendShape()
{
//フォルダを用意する
var path = AssetDatabase.GetAssetPath(avatar);
path = path.Replace(Path.GetFileName(path), "") + "/Animations";
if (!Directory.Exists(path)) Directory.CreateDirectory(path);
Mesh mesh;
for (int i = 0; i < avatar.transform.childCount; i++)
{
//BlendShapeがあるメッシュを特定する
var skinnedMesh = avatar.transform.GetChild(i).GetComponent<SkinnedMeshRenderer>();
if (skinnedMesh != null && skinnedMesh.sharedMesh.blendShapeCount > 0)
{
mesh = skinnedMesh.sharedMesh;
//アニメーションを生成する
for (int j = 0; j < mesh.blendShapeCount; j++)
{
var name = mesh.GetBlendShapeName(j);
var clip = new AnimationClip();
var serializedClip = new SerializedObject(clip);
serializedClip.FindProperty("m_AnimationClipSettings.m_LoopTime").boolValue = true;
serializedClip.ApplyModifiedProperties();
var curve = new AnimationCurve(
new Keyframe(0 / 60f, 100f),
new Keyframe(1 / 60f, 100f)
);
clip.SetCurve(mesh.name, typeof(SkinnedMeshRenderer), "blendShape." + name, curve);
AssetDatabase.CreateAsset(clip, path + "/" + name + ".anim");
}
}
}
}
}
アニメーションを生成する
- スクリプトを実行する
- C# スクリプトを「GenerateAnimationFromBlendShape」という名前で作成する
(右クリック > Create > C# Sciprt) - スクリプトをダブルクリックする
- 上記のコードをコピペして保存する
- GameObject を作成する。(右クリック > Create Empty)
- スクリプトをドラッグ&ドロップで GameObject にアタッチする
- Assets フォルダにある 3D モデルを、変数(Avatar)にドラッグ&ドロップでセットする
- 三点リーダーをクリックして表示される「GenerateAnimationFromBlendShape」を実行する
- C# スクリプトを「GenerateAnimationFromBlendShape」という名前で作成する


- Animations というフォルダが新しく作成されたことを確認する
- BlendShape ごとのアニメーションファイルが作成されたことを確認する。
- トラッキング(まばたきやリップシンク)で利用するアニメーションファイルを削除する

- 作成したスクリプトとゲームオブジェクトを削除する
- 削除しないとアバターをアップロードする際にエラーが発生する
proxy_tpose を転写する
Blend Shape のみ設定したアニメーションを再生すると、アバターが中腰になってしまう。

- proxy_tpose のキーを全選択してコピーする

- 全てのアニメーションに proxy_tpose のキーをペーストする

所感
- スクリプトには必要最低限のコードしか書いていないので、適宜修正して使ってほしい。
- 暇なときに proxy_tpose のキーを転写するようスクリプトを修正したい。