Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
VRMBlendShapeProxyからAnimationClipをはくやつ
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using VRM;
public class BlendShapeAnimationExpoter : EditorWindow
{
//対象のVRMBlendShapeProxy
public VRMBlendShapeProxy proxy;
public string savePath;
//Animatorとかがアタッチされているオブジェクト
private GameObject targetRoot;
//チェックボックスの状態を管理する用
[Serializable]
public class TargetBlendShapeClip
{
public string blendShapeClipName;
public bool isExport;
}
private List<TargetBlendShapeClip> targetBlendShapeClips = new List<TargetBlendShapeClip>();
private Dictionary<string ,bool> targetDictionary;
/*
[ContextMenu("test")]
public void test()
{
exportBlendShapeProxyForAnimationClip();
}
*/
private void exportBlendShapeProxyForAnimationClip()
{
targetRoot = proxy.gameObject;
//BlendShapeProxyの個数
int clipCount = proxy.BlendShapeAvatar.Clips.Count;
for (int i = 0; i < clipCount; i++)
{
//i番目のBlendShapeClipを取得
var blendShapeClip = proxy.BlendShapeAvatar.Clips[i];
//チェックボックスがFalseだったときは飛ばす
if (!targetDictionary[blendShapeClip.BlendShapeName])
{
continue;
}
//空のAnimationClipを作成
AnimationClip animclip = new AnimationClip();
EditorCurveBinding curveBinding = new EditorCurveBinding();
//BlendShapeClipで使われているBlendShapeをそれぞれ参照して、weightをAnimationClipに書き込む
for (int j = 0; j < blendShapeClip.Values.Length; j++)
{
//i番目のBlendShapeClipで使われているj番目のSkinnedMeshRendererのある相対パスを取得(ややこい)
var relativePath = blendShapeClip.Values[j].RelativePath;
//パスからSkinnedMeshRendererとSharedMeshを取得
var skinnedMeshRenderer = targetRoot.transform.Find(relativePath).GetComponent<SkinnedMeshRenderer>();
var sharedMesh = skinnedMeshRenderer.sharedMesh;
//SharedMeshからBlendShapeの名前とを引っ張ってくる
var blendShapeName = sharedMesh.GetBlendShapeName(blendShapeClip.Values[j].Index);
var blendShapeWeight = blendShapeClip.Values[j].Weight;
//一旦BlendShapeにBlendShapeClipで指定されている値をいれてAnimationClipを生成しやすくする
skinnedMeshRenderer.SetBlendShapeWeight(blendShapeClip.Values[j].Index, blendShapeWeight);
//案メーション作成
createAnimation(animclip, curveBinding, relativePath,
"blendShape." + blendShapeName, blendShapeWeight);
//BlendShapeの値を0に戻す
skinnedMeshRenderer.SetBlendShapeWeight(blendShapeClip.Values[j].Index, 0);
}
if (blendShapeClip.Values.Length != 0)
{
//AnimationClipとして書き出す
AssetDatabase.CreateAsset(
animclip,
AssetDatabase.GenerateUniqueAssetPath("Assets/"+savePath+"/"+blendShapeClip.BlendShapeName+".anim")
);
AssetDatabase.SaveAssets();
Debug.Log("Generate "+blendShapeClip.BlendShapeName+".anim !");
AssetDatabase.Refresh();
}
}
}
private void initDictionary()
{
targetDictionary = new Dictionary<string, bool>();
for (int i = 0; i < proxy.BlendShapeAvatar.Clips.Count; i++)
{
targetDictionary.Add(targetBlendShapeClips[i].blendShapeClipName, targetBlendShapeClips[i].isExport);
}
}
//AnimationClipに書き込んでいく関数
private void createAnimation(AnimationClip targetAnimClip, EditorCurveBinding curveBinding, string curvePath,
string curvePropertyName, float keyWeight)
{
curveBinding.path = curvePath;
curveBinding.type = typeof(SkinnedMeshRenderer);
curveBinding.propertyName = curvePropertyName;
AnimationCurve curve = new AnimationCurve();
curve.AddKey(0f, keyWeight);
AnimationUtility.SetEditorCurve(targetAnimClip, curveBinding, curve);
}
[MenuItem("VRM/VRMBlendShapeProxyAnimationExporter")]
static void Open ()
{
var exampleWindow = CreateInstance<BlendShapeAnimationExpoter> ();
exampleWindow.Show ();
}
private void OnGUI()
{
EditorGUIUtility.labelWidth = 200;
EditorGUILayout.BeginVertical();
proxy = (VRMBlendShapeProxy) EditorGUILayout.ObjectField("TragetVRMBlendShapeProxy",proxy, typeof(VRMBlendShapeProxy), true);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel ("SavePath:Assets/");
savePath = EditorGUILayout.TextField(savePath);
EditorGUILayout.PrefixLabel ("/");
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
if (proxy == null)
{
return;
}
for (int i = 0; i < proxy.BlendShapeAvatar.Clips.Count; i++)
{
targetBlendShapeClips.Add(new TargetBlendShapeClip());
EditorGUILayout.BeginHorizontal();
targetBlendShapeClips[i].blendShapeClipName = proxy.BlendShapeAvatar.Clips[i].BlendShapeName;
targetBlendShapeClips[i].isExport = EditorGUILayout.Toggle(targetBlendShapeClips[i].blendShapeClipName, targetBlendShapeClips[i].isExport);
EditorGUILayout.EndHorizontal();
}
if( GUILayout.Button( "Generate AnimationClip !" ) )
{
if (proxy == null)
{
Debug.LogError("VRMBlendShapeProxyがセットされていません!");
return;
}
initDictionary();
exportBlendShapeProxyForAnimationClip();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.