この記事は前回の続きになります
VRC用の拡張Editorを作ってみよう(4)
#目次
1.準備
2.OnGUIを作る
3.Animationを作るコードを書く
4.AddAnimationを呼び出す
5.動作確認する
6.次回
#1.準備
##Animationを保管するフォルダーを作る
アニメーションを保管するためのフォルダーを作っておきます
場所は自分の好きな場所で大丈夫です
これでアニメーションフォルダーは完成しました
##Editorフォルダーに新しくC#スクリプトを作る
新しくEditorを作りたいので、最初に作ったEditorフォルダーに、新しくC#スクリプトを作ります
名前は分かりやすい名前で作りましょう
今回は__AnimationEditor__にしました
これでC#スクリプトは完成しました
##Editorの初期設定をする
###usingを追加する
Editorとして機能させるためのusingと、今回使うusingを追加していきます
今回はこの二つを追加します
using UnityEditor;
using VRC.SDK3.Avatars.Components;
これでusingの追加ができました
###Menuアイテムを作る
メニューバーに表示するMenuアイテムを作ります
自分の名前など、好きなように設定してもらって大丈夫です
今回私は__AnimationEditor/AnimationEditor__で作ることにしました
[MenuItem("AnimationEditor/AnimationEditor")]
これでメニューバーに表示されるようになりました
###Windowを取得する
publicな、値を返さない静的メソッドを作ります
名前は__ShowWindow__などにしておきます
メソッドが出来たら、EditorWindow.GetWindowをつかって、(今回の場合)AnimationEditorを取得します
public static void ShowWindow()
{
EditorWindow.GetWindow<AnimationEditor>(true, "AnimationEditor");
}
これでウィンドウがひらけるようになりました
###Hierarchyからパスを取得できるようにする
後でアニメーションを作るときに、アバターの階層が取得できなかったので、それ用のメソッドを作りました
今回はそれを使用するために、コピー&ペーストしていきます
private static string GetHierarchyPath(GameObject targetObj)
{
List<GameObject> objPath = new List<GameObject>();
objPath.Add(targetObj);
for (int i = 0; objPath[i].transform.parent != null; i++)
objPath.Add(objPath[i].transform.parent.gameObject);
string path = objPath[objPath.Count - 2].gameObject.name; //今回の場合avatar(先頭のオブジェクトが不要)なのでCount - 2にする。必要な場合は - 1 に変更
for (int i = objPath.Count - 3; i >= 0; i--) //こっちもCount - 3にする。必要な場合は - 2にする
path += "/" + objPath[i].gameObject.name;
return path;
}
空いているところにコピーができたら使えるようになります
コードの説明はこちら
これで準備は終わりました
#2.OnGUIを作る
##OnGUIメソッドを作る
privateな値を返さないメソッド、OnGUIを作ります
private void OnGUI()
{
}
これでOnGUIメソッドは完成しました
##変数を宣言する
今回宣言する変数は、
アバター,(VRCAvatarDescriptor),[avatar]
アニメーションの名前,(string),[animationName]
オンオフするオブジェクト,(GameObject),[targetObj]
アニメーションフォルダーのパス,(string),[animFolderPath]
アニメーションフォルダーのパスは、さっき作ったAnimationフォルダーのパスをコピーしてきましょう
これらを全てprivateで作っていきます
(もちろん今回もOnGUIの上に書きますよ)
private VRCAvatarDescriptor avatar;
private string animationName;
private GameObject targetObj;
private string animFolderPath = "Assets/test/Animation";
これで変数は完成しました
##変数に代入する
上で作った変数に、値を代入していきます
avatarとtargetObjは、いつも通りObjectFieldを使いますが、animationNameだけTextFieldを使用します
TextFieldの使い方はこうです
EditorGUILayout.TextField("label", "text");
これを使って代入していきます
TextFieldに、キャストは必要ありません
(OnGUI内に書きます)
avatar = EditorGUILayout.ObjectField("Avatar", avatar, typeof(VRCAvatarDescriptor), true) as VRCAvatarDescriptor;
animationName = EditorGUILayout.TextField("animationName", animationName);
targetObj = EditorGUILayout.ObjectField("TargetObject", targetObj, typeof(GameObject), true) as GameObject;
これで変数への代入ができました
##ボタンを作る
まずはIF文を書いていきます
(OnGUIの中に書きます)
avatarがnullではない時__かつ__、アニメーションの名前がnullではない時__かつ__、ターゲットオブジェクトがnullではない時、を、条件にします
if (avatar && animationName != null && targetObj)
{
}
IF文が完成しました
次に、ボタンを作っていきます
(IF文の中に作ります)
ボタンの名前は何でも大丈夫です
今回私はAnimation作成にしました
if (avatar && animationName != null && targetObj)
{
if (GUILayout.Button("Animation作成"))
{
}
}
これでボタンが完成しました
#3.Animationを作るコードを書く
##コードを書くためのメソッドを作る
privateな、値を返さないメソッドを作ります
メソッド名はわかりやすい名前にします
今回私は、__AddAnimation__にしました
private void AddAnimation()
{
}
これでメソッドが完成しました
##メソッドを完成させる
まずは、CreateAssetを使って、新しくAnimationClipを作るようにします
最初に作った変数、animFolderPathをパスとして使用します
作成するときの名前は、変数animationNameを使います
アニメーションを二つ、OnとOffを作成したいので、animationNameにOnとOffを付けくわえて
二つアニメーションを作成します
AssetDatabase.CreateAsset(new AnimationClip(), animFolderPath + "/" + animationName + "On.anim");
AssetDatabase.CreateAsset(new AnimationClip(), animFolderPath + "/" + animationName + "Off.anim");
次に、今作ったアニメーションを、AnimationClip型の変数animOnとanimOffを宣言して代入します
代入する時は、LoadAssetAtPathを使用します
AnimationClip animOn = AssetDatabase.LoadAssetAtPath(animFolderPath + "/" + animationName + "On.anim", typeof(AnimationClip)) as AnimationClip;
AnimationClip animOff = AssetDatabase.LoadAssetAtPath(animFolderPath + "/" + animationName + "Off.anim", typeof(AnimationClip)) as AnimationClip;
これで代入ができました
##targetObjの現在のパスを取得する
GetHierarchyPathを呼び出して、string型の変数に代入します
変数の名前はpathにします
string path = GetHierarchyPath(targetObj);
これでパスを取得できました
##アニメーションにKeyFrameを追加する
KeyFrameを追加するために、AnimationCurveを使用します
Animationcurve型の変数を宣言して、new AnimationCurve(new Keyframe( , ))を代入します
keyframeの使い方はこの通りです
Keyframe("フレーム数", "Value")
これを使用して、新しくcurveOnとcurveOffを宣言します
__curveOn__は、ゲームオブジェクトを有効化するため、Valueを1にします
__curveOff__は、ゲームオブジェクトを有効化するため、Valueを0にします
フレーム数は二つとも0です
AnimationCurve curveOn = new AnimationCurve(new Keyframe(0f, 1f));
AnimationCurve curveOff = new AnimationCurve(new Keyframe(0f, 0f));
次にこれをAnimationClipにセットしていきます
セットには__AnimationClip.SetCurve__を使用します
使い方はこの通りです
AnimationClip.SetCurve("relativePath", "type", "propertyName", "curve");
これをanimOnと、AnimOff用に作っていきます
animOn.SetCurve(path, typeof(GameObject),"m_IsActive", curveOn);
animOff.SetCurve(path, typeof(GameObject), "m_IsActive", curveOff);
これでアニメーションにKeyFrameを追加することができました
#4.AddAnimationを呼び出す
最初に作ったボタンから、AddAnimationを呼び出せるようにします
ボタンの中(IF文)に書いていきます
if (avatar && animationName != null && targetObj)
{
if (GUILayout.Button("Animation作成"))
{
AddAnimation(); //ここに追加
}
}
これで呼び出せるようになりました
#5.動作確認する
オブジェクトを用意します
VRCAvatarDescriptorが入ったAvatarと、適当に追加したゲームオブジェクトを用意します
用意ができたらEditorを開きます
追加していきましょう
追加ができたら、Animation作成を押してみましょう
Animationフォルダーに追加されていれば成功です
アニメーションは[ウィンドウ/アニメーション/アニメーション]で確認できます
#6.次回
次回はAnimator編です