AvatarをセットアップするEditorを作る(FX編)｜VRC用の拡張Editorを作ってみよう(3)

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

#目次
1.不要なコードを削除する
2.VRCAvatarDescriptorが入ってない場合自動でコンポーネントを追加するようにする
3.FXLayerが入っているか確認して入っていなければ追加するコードを書く
4.ボタンを押すと処理が行われるようにする
5.動作確認をする
6.次回

#1.不要なコードを削除する
##削除するコード
__InsertObjectメソッド__はすべて消します

```c#
//すべて消す
private void InsertObject()
{
	gameObject.transform.SetParent(avatar.transform);
}
```

__if(GUILayout.Button)__もすべて消す

```c#
if (GUILayout.Button("オブジェクトを入れる"))
{
	InsertObject(); //中のInsertObject();も消す
}
```

前回作成した__GameObjectの変数__と__ObjectField__を削除する

```c#
//gameObjectはすべて消す
private GameObject gameObject;
gameObject = EditorGUILayout.ObjectField("gameObject", gameObject, typeof(GameObject), true) as GameObject;
```

全て消すとこのようになると思います

```c#
public class TestEditor : EditorWindow
{
    [MenuItem("TestEditor/TestEditor")]

	public static void ShowWindow()
	{
		EditorWindow.GetWindow<TestEditor>(true, "TestEditor");
	}

	private GameObject avatar;

	private void OnGUI()
	{
		avatar = EditorGUILayout.ObjectField("Avatar", avatar, typeof(GameObject), true) as GameObject;
	}
}
```

これでコードの削除ができました

#2.VRCAvatarDescriptorが入ってない場合自動でコンポーネントを追加するようにする
##AvatarのObjectFieldをVRCAvatarDescriptorからGameObjectに書き換える
前回書いた__VRCAvatarDescriptorタイプ__の変数__Avatar__を__GameObject__にしていきます
まずは変数から変更してきます

```c#
//変更前
private VRCAvatarDescriptor avatar;

//変更後
private GameObject avatar;
```

__VRCAvatarDescriptor__を__GameObject__に書き換えるだけで変更できると思います
次にObjectFieldを変更していきます

```c#
//変更前
avatar = EditorGUILayout.ObjectField("Avatar", avatar, typeof(VRCAvatarDescriptor), true) as VRCAvatarDescriptor;

//変更後
avatar = EditorGUILayout.ObjectField("Avatar", avatar, typeof(GameObject), true) as GameObject;
```

オブジェクトタイプとキャストをVRCAvatarDescriptorからGameObjectに変更しました
これで書き換えができました

##VRCAvatarDescriptorを追加する用のメソッドを作る
前回と同じようにメソッドを作っていきます
今回も__値を返さないメソッド__を作ります
名前は適当につけて・・・

```c#
private void AddDescriptor()
{
	
}
```

こんな感じになりました

##VRCAvatarDescriptorが入っているかを確認して、入っていなければ追加するコードを書く
コードは先ほど作成した__AddDescriptorの中__に書いていきます
###まずはVRCAvatarDescriptorが入っているかを確認します
if文で真・偽を判定し、Avatar.__GetComponent__を使ってコンポーネントを取得します
コンポーネントを取得できなければ__真を返すようにしたい__ので、GetComponentの先頭に __否定「!」__ を付けます
GetComponentで__取得するコンポーネントはVRCAvatarDescriptor__です
今回のコードはこうなりました

```c#
if (!avatar.GetComponent<VRCAvatarDescriptor>())
{
			
}
```

これで確認できるようになりました

###次にVRCAvatarDescriptorを追加していきます
Avatar.__AddComponent__を使ってコンポーネントを追加できるようにします
AddComponentで__追加するコンポーネントはVRCAvatarDescriptor__です
今回のコードはこうなりました

```c#
if (!avatar.GetComponent<VRCAvatarDescriptor>())
{
	avatar.AddComponent<VRCAvatarDescriptor>();
}
```

これでコンポーネントがなければ追加するコードが完成しました

#3.FXLayerが入っているか確認して入っていなければ追加するコードを書く
##FXLayerを保管するフォルダーを作成する
準備としてFXLayerを保管するフォルダーを作っていきます
フォルダーを作る場所は自由です
名前は分かりやすいように__FxLayer__などつけておきましょう
![FxLayer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286080/6cfb31a8-4d17-0dae-9974-d2b64df0e889.png)
フォルダーが完成したら__フォルダーのパス__を取得します
FXLayerフォルダーを右クリックしてパスをコピーします
![pathcopy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286080/59402f83-2ebf-0436-a83a-4a9caf4337f6.png)
パスのコピーができたら新しく変数を宣言していきます
今回は__OnGUIの上__で宣言します
privateなstring型の変数createFXPathを宣言します
宣言したcreateFXPathに、先ほどコピーしたパスを代入します
宣言ができるとこんな感じになると思います

```c#
private string createFXPath = "Assets/test/FxLayer";
private void OnGUI()
{
```
FXLayerを保管するフォルダーができました
##FXLayerをコピーするためのパスを取得する
FXLayerをコピーするパスの変数を作っていきます
今回も__OnGUIの上__で宣言します
privateなstring型の変数copyFXPathを宣言します
宣言したcopyFXPathに、FXLayerが入っている
Assets/VRCSDK/Examples3/Animation/Controllers/vrc_AvatarV3HandsLayer.controller
を代入します
宣言ができるとこんな感じになると思います

```c#
private string copyFXPath = "Assets/VRCSDK/Examples3/Animation/Controllers/vrc_AvatarV3HandsLayer.controller";
```

これで準備はできました

##FXLayerを追加する用のメソッドを作る
FXLayerを追加する用のメソッドを作っていきます
今回も__値を返さないメソッド__を作ります
名前は適当につけて・・・
こんな感じのコードになると思います

```c#
private void SetupFXLayer()
{

}
```

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

##Playeble LayersのCustomizeが有効になっているかを確認して無効になっていた場合有効にする
先ほど作成したSetupFXLayerの中に書いていきます
###最初に変数を作る
後から使いやすいように最初に変数を作っていきます
__VRCAvatarDescriptorタイプ__の__avatarDescriptor変数__を作って・・・
avatarDescriptor変数に__avatar.GetComponentで取得したVRCAvatarDescriptorを代入__していきます
今回のコードはこうなります

```c#
VRCAvatarDescriptor avatarDescriptor = avatar.GetComponent<VRCAvatarDescriptor>();
```
これで変数はできました

###次にPlayeble LayersのCustomizeが有効になっているかを確認する
Playeble LayersのCustomizeが有効になっているかを確認するコードを書いていきます
有効になっているかの確認はVRCAvatarDescriptor.__customizeAnimationLayers__で確認できます
__if文でcustomizeAnimationLayersが偽の場合、真に変更するコード__を書いてきます
先ほど作成した変数を使用して・・・
今回のコードはこうなりました

```c#
if (!avatarDescriptor.customizeAnimationLayers)
{
	avatarDescriptor.customizeAnimationLayers = true; //trueで偽から真に変える
}
```
これでPlayeble LayersのCustomizeが有効になっているかを確認して、無効になっていた場合有効にするコードが完成しました

##FXLayerがデフォルトになっているか確認して、デフォルトになっていたらカスタムできるようにする
SetupFXLayer()の中に書いていきます
FXLayerの取得はVRCAvatarDescriptor.__baseAnimationLayers[4]__を使用することで取得できます
FXLayer以外にも、配列の番号を変えるとほかのLayerが取得できます

|Base|Additive|Gesture|Action|FX
|---|---|---|---|---|
|[0]|[1]|[2]|[3]|[4]|

デフォルトの確認はbaseAnimationLayers[].__isDefault__を使用して確認できます
今回はデフォルトになっているかの確認をしたいので、if文を使います
確認用のコードが完成したら、if文の中にisDefaultが真のときのコードを書きます
カスタムする場合、__isDefaultをfalse__に変えてあげるとカスタムできるようになります
今回のコードはこうなりました

```c#
if (avatarDescriptor.baseAnimationLayers[4].isDefault) //avatarのFXLayerがデフォルトになってるか判定する
{
	avatarDescriptor.baseAnimationLayers[4].isDefault = false; //デフォルトになっていたらデフォルトを真から偽に変える
}
```
これでFXコントローラーのカスタムができるようになりました

##FXコントローラーを追加する
先ほどカスタム状態にしたFXLayerの中にFXコントローラーを追加していきます
コードは__先ほど作ったif文の中__に書きます
###初めにFXコントローラーをコピーする
コピーは__AssetDatabase.CopyAsset__を使用します
使い方はこの通りです

```c#
AssetDatabase.CopyAsset("コピー元のパス" , "コピー後のパス");
```

これに先ほど準備したパス変数を書いていきます
__コピー元のパスはcopyFXLayer
コピー後のパスはcreateFXLayer__
ですがコピー後のパスcreateFXLayerは__このままでは使用できない__のでアバターごとに作成されるようにアバターの名前を追加して作成するようにします
今回はこのようにします
コピー後のパス + "アバターの名前" + コントローラーの拡張子
__createFXPath + "/" + avatar.name + "_HandsLayer.controller"__
これを使用してコードを書いていきます
今回のコードはこうなります

```c#
AssetDatabase.CopyAsset(copyFXPath, createFXPath + "/" + avatar.name + "_HandsLayer.controller");
```
これでFxLayerにコントローラーが作成されました

###FXコントローラーを追加する
FXLayer.Controllerの取得はavatarDescriptor.baseAnimationLayers[4].__animatorController__を使用して取得できます

###取得したFXコントローラーにコントローラーを入れる
取得したFXコントローラーにコントローラーを入れるには__Assetからロードする必要__があるので
__AssetDatabase.LoadAssetAtPath__を使用します
書き方はこの通りです

```c#
AssetDatabase.LoadAssetAtPath("ロードするファイルのパス", "オブジェクトのタイプ")
```

ロードするファイルのパスは先ほど書いた
__createFXPath + "/" + avatar.name + "_HandsLayer.controller"__
を利用します
オブジェクトタイプは__RuntimeAnimatorController__です
上記のFXコントローラーを追加する、を組み合わせて書いていきます
今回はこのようになりました

```c#
avatarDescriptor.baseAnimationLayers[4].animatorController = AssetDatabase.LoadAssetAtPath(createFXPath + "/" + avatar.name + "_HandsLayer.controller", typeof(RuntimeAnimatorController))
```

前回と同じようにこのままでは変換ができないのでキャストを用意します
コードの末尾に__as RuntimeAnimatorController__を追加します
これでコードが完成しました

#4.ボタンを押すと処理が行われるようにする
##ボタンに条件を付ける
条件が真・偽であればボタンを表示させるコードを__OnGUIの中に__書いていきます
今回はまず__avatarが入っているか__をif文で判定し、真だった場合に__VRCAvatarDescriptor__が入っているか、いないかをif文で判定してボタンを表示できるようにします
__真の場合はSetupFXLayer()を実行
偽の場合はAddDescriptor()を実行__します
判定用のif文ができたらボタンの表示名を適当につけてボタンを作ります
ボタンができたらコードはこんな感じになると思います

```c#
if (avatar)
{
	if (avatar.GetComponent<VRCAvatarDescriptor>())
	{
		if (GUILayout.Button("アバターのFXLayerをセットアップする"))
		{
			
		}
	}
	else
	{
		if (GUILayout.Button("アバターにVRCAvatarDescriptorを入れる"))
		{
			
		}
	}
}
```

##ボタンでメソッドを呼び出すようにする
今回作ったメソッド二つをボタンのif文の中に追加していきます
今回作ったメソッドは
__AddDescriptor__と__SetupFXLayer__なので引数なしで呼び出していきます
コードはこうなります

```c#
if (avatar)
{
	if (avatar.GetComponent<VRCAvatarDescriptor>())
	{
		if (GUILayout.Button("アバターのFXLayerをセットアップする"))
		{
			SetupFXLayer();
		}
	}
	else
	{
		if (GUILayout.Button("アバターにVRCAvatarDescriptorを入れる"))
		{
			AddDescriptor();
		}
	}
}
```

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

#5.動作確認をする
まずはCtrl + Sを押してスクリプトを__保存__しましょう
次にUnityに戻って動作確認します
##準備
準備として、空のオブジェクトをヒエラルキーに作成します
分かりやすくするために名前はAvatarなどに変更しましょう
![avatar.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286080/0730fa1a-c077-f26b-ffac-6784e81bde9d.png)
これで準備ができました

##動作確認
TestEditorを開きます
EditorのAvatarにゲームオブジェクトのAvatarをセットしましょう
![Editor7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286080/aeffcc87-6d0f-7386-4ae7-15374d420592.png)

セットができたら__アバターにVRCAvatarDescriptorを入れる__を押してみましょう
押したら一度AvatarのInspectorに移りVRCAavatarDescriptorが入っているのが確認します
![Descriptor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286080/d9a89c21-7c95-1c0d-49ab-59680ba34701.png)
VRCAavatarDescriptorが入っているのを確認できたと思います
確認ができたらもう一度Editorに戻り__アバターのFXLayerをセットアップする__を押します
押したらもう一度AvatarのInspectorに移りFXLayerをセットアップされているか確認します
![fxlayer (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286080/b316ebdc-7fee-cc0c-84d6-4b7091fd41c5.png)

確認ができたら今回は終了です

__※連続で押すとVRCAvatarDescriptorが生成される前に操作してしまいエラーが出ることがあります__

#6.次回
次回はExMenuとExParameterを自動でセットアップするEditorを作っていこうかなと思います

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