VRChat アバターで使用するために、BlendShape から1フレームのループアニメーションを作りたい。BlendShape のキーのみだと、アニメーションを再生した時にアバターが中腰になってしまうので、proxy_tpose のキーを追加する必要がある。
BlendShape のみを利用してアニメーションを生成する場合は、「BlendShape からアニメーションを生成する」という記事を参照してほしい。
proxy_tpose を複製する
- proxy_tpose を複製する(Ctrl + D)
- 複製したものを Assets の適当なフォルダに移動させる

- 複製した proxy_tpose をダブルクリックして、Animation のタブを開く
- フレーム 0:00 にあるキーを全てコピーして、フレーム 0:01 に貼り付ける

C# スクリプト
using System.IO;
using UnityEditor;
using UnityEngine;
public class GenerateAnimFromBlendshapeAndTposeAnim : MonoBehaviour
{
public GameObject avatar;
public AnimationClip clipTpose;
[ContextMenu("GenerateAnimatonFromBlendShape")]
public void GenerateAnimatonFromBlendShape()
{
//パスを得る
var pathAvatar = AssetDatabase.GetAssetPath(avatar);
var pathClipTpose = AssetDatabase.GetAssetPath(clipTpose);
//フォルダ(Animations)を作成する
var pathDirAnims = pathAvatar.Replace(Path.GetFileName(pathAvatar), "") + "/Animations";
if (!Directory.Exists(pathDirAnims)) Directory.CreateDirectory(pathDirAnims);
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++)
{
//BlendShapeの名前を得る
var blendshapeName = mesh.GetBlendShapeName(j);
//proxy_tposeをフォルダ(Animations)にコピーして、変数にセットする
var pathAnimBlendshape = pathDirAnims + "/" + blendshapeName + ".anim";
AssetDatabase.CopyAsset(pathClipTpose, pathAnimBlendshape);
var clipBlendshape =
(AnimationClip)AssetDatabase.LoadAssetAtPath(pathAnimBlendshape,typeof(AnimationClip));
//アニメーションを設定する
var serializedClip = new SerializedObject(clipBlendshape);
serializedClip.FindProperty("m_AnimationClipSettings.m_LoopTime").boolValue = true;
serializedClip.ApplyModifiedProperties();
var curve = new AnimationCurve(
new Keyframe(0 / 60f, 100f),
new Keyframe(1 / 60f, 100f)
);
clipBlendshape.SetCurve(mesh.name, typeof(SkinnedMeshRenderer), "blendShape." + blendshapeName, curve);
}
}
}
}
}
- 「GenerateAnimFromBlendshapeAndTposeAnim」という名前で C# スクリプトを作成する(参考画像内①)
- スクリプトをダブルクリックで開く(参考画像内①)
- 上記のスクリプトをコピペして上書き保存する
- Scene に GameObejct を新規作成する(参考画像内②)
- スクリプトをドラッグ&ドロップでアタッチする(参考画像内③)
- Avatar に アバター(FBX ファイル等)をドラッグ&ドロップでセットする(参考画像内④)
- Clip Tpose に 先に複製した proxy_tpose をドラッグ&ドロップでセットする(参考画像内⑤)

- 三点リーダをクリックする
- GenerateAnimationFromBlendShape をクリックする

- Animations というフォルダが作成されたことを確認する
- 全ての BlendShape に関して、アニメーションが作成されたことを確認する

- トラッキング(まばたきやリップシンク)で利用するアニメーションファイルを削除する

所感
- スクリプトには必要最低限のコードしか書いていないので、適宜修正して使ってほしい。
- proxy_tpose の複製、および 0:00 から 0:01 へのキーのコピーに関しても、スクリプトに書きたかったが、面倒そうなのでやめた。