アバターの物を出し入れできるようにするEditorを作る(Animation編)｜VRC用の拡張Editorを作ってみよう(5)

この記事は前回の続きになります
[VRC用の拡張Editorを作ってみよう(4)](https://qiita.com/Milcia/items/37786bff5b4c2d7eceb0)

#目次
1.準備
2.OnGUIを作る
3.Animationを作るコードを書く
4.AddAnimationを呼び出す
5.動作確認する
6.次回

#1.準備
##Animationを保管するフォルダーを作る
アニメーションを保管するためのフォルダーを作っておきます
場所は自分の好きな場所で大丈夫です
![Animation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286080/88fe161c-4288-f37d-eccf-b25e96018365.png)
これでアニメーションフォルダーは完成しました

##Editorフォルダーに新しくC#スクリプトを作る
新しくEditorを作りたいので、最初に作ったEditorフォルダーに、新しくC#スクリプトを作ります
名前は分かりやすい名前で作りましょう
今回は__AnimationEditor__にしました
![AnimationEditor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286080/ea7bec59-b2a8-e515-ee18-2a8d1e3465b0.png)
これでC#スクリプトは完成しました

##Editorの初期設定をする
###usingを追加する
Editorとして機能させるためのusingと、今回使うusingを追加していきます
今回はこの二つを追加します

```c#
using UnityEditor;
using VRC.SDK3.Avatars.Components;
```
これでusingの追加ができました

###Menuアイテムを作る
メニューバーに表示するMenuアイテムを作ります
自分の名前など、好きなように設定してもらって大丈夫です
今回私は__AnimationEditor/AnimationEditor__で作ることにしました

```c#
[MenuItem("AnimationEditor/AnimationEditor")]
```
これでメニューバーに表示されるようになりました

###Windowを取得する
publicな、値を返さない静的メソッドを作ります
名前は__ShowWindow__などにしておきます
メソッドが出来たら、EditorWindow.GetWindowをつかって、(今回の場合)AnimationEditorを取得します

```c#
public static void ShowWindow()
{
	EditorWindow.GetWindow<AnimationEditor>(true, "AnimationEditor");
}
```
これでウィンドウがひらけるようになりました

###Hierarchyからパスを取得できるようにする
後でアニメーションを作るときに、アバターの階層が取得できなかったので、それ用のメソッドを作りました
今回はそれを使用するために、コピー&ペーストしていきます

```c#
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;
}
```
空いているところにコピーができたら使えるようになります
コードの説明は[こちら](https://qiita.com/Milcia/items/d6412d4c07cc2e9ffe5a)
これで準備は終わりました

#2.OnGUIを作る
##OnGUIメソッドを作る
privateな値を返さないメソッド、OnGUIを作ります

```c#
private void OnGUI()
{

}
```
これでOnGUIメソッドは完成しました

##変数を宣言する
今回宣言する変数は、
__アバター,(VRCAvatarDescriptor),[avatar]
アニメーションの名前,(string),[animationName]
オンオフするオブジェクト,(GameObject),[targetObj]
アニメーションフォルダーのパス,(string),[animFolderPath]__
アニメーションフォルダーのパスは、さっき作ったAnimationフォルダーのパスをコピーしてきましょう
これらを全てprivateで作っていきます
(もちろん今回もOnGUIの上に書きますよ)

```c#
private VRCAvatarDescriptor avatar;
private string animationName;
private GameObject targetObj;

private string animFolderPath = "Assets/test/Animation";
```
これで変数は完成しました

##変数に代入する
上で作った変数に、値を代入していきます
avatarとtargetObjは、いつも通りObjectFieldを使いますが、__animationNameだけTextFieldを使用します__
TextFieldの使い方はこうです

```c#
EditorGUILayout.TextField("label", "text");
```

これを使って代入していきます
__TextFieldに、キャストは必要ありません__
(OnGUI内に書きます)

```c#
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ではない時、を、条件にします

```c#
if (avatar && animationName != null && targetObj)
{
	
}
```
IF文が完成しました
次に、ボタンを作っていきます
(IF文の中に作ります)
ボタンの名前は何でも大丈夫です
今回私はAnimation作成にしました

```c#
if (avatar && animationName != null && targetObj)
{
	if (GUILayout.Button("Animation作成"))
	{
		
	}	
}
```
これでボタンが完成しました

#3.Animationを作るコードを書く
##コードを書くためのメソッドを作る
privateな、値を返さないメソッドを作ります
メソッド名はわかりやすい名前にします
今回私は、__AddAnimation__にしました

```c#
private void AddAnimation()
{

}
```

これでメソッドが完成しました

##メソッドを完成させる
まずは、CreateAssetを使って、新しくAnimationClipを作るようにします
最初に作った変数、animFolderPathをパスとして使用します
作成するときの名前は、変数animationNameを使います
アニメーションを二つ、OnとOffを作成したいので、animationNameにOnとOffを付けくわえて
二つアニメーションを作成します

```c#
AssetDatabase.CreateAsset(new AnimationClip(), animFolderPath + "/" + animationName + "On.anim");
AssetDatabase.CreateAsset(new AnimationClip(), animFolderPath + "/" + animationName + "Off.anim");
```

次に、今作ったアニメーションを、__AnimationClip型の変数animOnとanimOffを宣言して代入します__
代入する時は、LoadAssetAtPathを使用します

```c#
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にします

```c#
string path = GetHierarchyPath(targetObj);
```
これでパスを取得できました

##アニメーションにKeyFrameを追加する
KeyFrameを追加するために、AnimationCurveを使用します
Animationcurve型の変数を宣言して、new AnimationCurve(new Keyframe( , ))を代入します
keyframeの使い方はこの通りです

```c#
Keyframe("フレーム数", "Value")
```
これを使用して、新しくcurveOnとcurveOffを宣言します
__curveOn__は、ゲームオブジェクトを有効化するため、__Valueを1にします__
__curveOff__は、ゲームオブジェクトを有効化するため、__Valueを0にします__
フレーム数は二つとも0です

```c#
AnimationCurve curveOn = new AnimationCurve(new Keyframe(0f, 1f));
AnimationCurve curveOff = new AnimationCurve(new Keyframe(0f, 0f));
```
次にこれをAnimationClipにセットしていきます
セットには__AnimationClip.SetCurve__を使用します
使い方はこの通りです

```c#
AnimationClip.SetCurve("relativePath", "type", "propertyName", "curve");
```
これをanimOnと、AnimOff用に作っていきます

```c#
animOn.SetCurve(path, typeof(GameObject),"m_IsActive", curveOn);
animOff.SetCurve(path, typeof(GameObject), "m_IsActive", curveOff);
```
これでアニメーションにKeyFrameを追加することができました

#4.AddAnimationを呼び出す
最初に作ったボタンから、AddAnimationを呼び出せるようにします
ボタンの中(IF文)に書いていきます

```c#
if (avatar && animationName != null && targetObj)
{
	if (GUILayout.Button("Animation作成"))
	{
		AddAnimation(); //ここに追加
	}
}
```

これで呼び出せるようになりました

#5.動作確認する
オブジェクトを用意します
VRCAvatarDescriptorが入ったAvatarと、適当に追加したゲームオブジェクトを用意します
![avatargame.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286080/fe7cf5e8-c56d-50f4-d84c-f1a8165b4157.png)
用意ができたらEditorを開きます
![editor10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286080/d9d2e85d-dbc5-1f8a-ff68-d311ebda8916.png)
追加していきましょう
![Editor11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286080/6b932044-c46d-d4c5-1dd2-45c52469440c.png)
追加ができたら、Animation作成を押してみましょう
![AnimationFolder.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286080/5d2d07f8-d19e-08f8-54b5-bf6b703e674f.png)
![animation2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286080/67306b61-a1f6-5b8e-2dbf-baac16188934.png)
Animationフォルダーに追加されていれば成功です
アニメーションは[ウィンドウ/アニメーション/アニメーション]で確認できます

#6.次回
次回はAnimator編です

[VRC用の拡張Editorを作ってみよう(6)](https://qiita.com/Milcia/items/2166786c0a33098b57ed)