Animation関連メモ(Animation Controllerの自動生成 + α)

 # やりたいこと
ここを参考 -> https://docs.unity3d.com/ScriptReference/Animations.AnimatorController.html

1. 32パターンの同じ構造をもつstateを用意
1. それぞれにBlendTreeをもつ
1. Transitionに関しては双方向
1. 自分自身に関してもTransitionをもつ

# できたもの

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1353403/e0105fd5-fbc8-1215-794e-101b68247513.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1353403/3e75f8ce-c20c-c1f5-2e83-aeb3023ac948.png)

## スクリプト

```CreateAnimationController.cs

using UnityEngine;
using UnityEditor;
using UnityEditor.Animations;
using System.Collections;
using System.Collections.Generic;

public class CreateAnimationController : MonoBehaviour
{
    [MenuItem("Window/Create Controller")]
    // Start is called before the first frame update

     //Referenced from empathetic dialogue
    static void CreateController()
    {
        List<string> _emotion_list = new List<string>{
        "surprised",
        "excited",
        "angry",
        "proud",
        "sad",
        "annoyed",
        "grateful",
        "lonely",
        "afraid",
        "terrified",
        "guilty",
        "impressed",
        "disgusted",
        "hopeful",
        "confident",
        "furious",
        "anxious",
        "anticipating",
        "joyful",
        "nostalgic",
        "disappointed",
        "prepared",
        "jealous",
        "content",
        "devastated",
        "embarrassed",
        "caring",
        "sentimental",
        "trusting",
        "ashamed",
        "apprehensive",
        "faithful",
        };

        var controller = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerAtPath("Assets/Resources/AnimationCreationController.controller");

        foreach(var emotion in _emotion_list){
            controller.AddParameter(emotion, AnimatorControllerParameterType.Float);
        }
        var rootStatemachine = controller.layers[0].stateMachine;
        var waitingState = rootStatemachine.AddState("waiting");
        rootStatemachine.defaultState = waitingState;
        waitingState.motion = Resources.Load( "wait") as AnimationClip;

        List<UnityEditor.Animations.AnimatorState> _states = new List<UnityEditor.Animations.AnimatorState>();

        for(int i = 0; i < _emotion_list.Count; i++ ){
            var _blendTree = new UnityEditor.Animations.BlendTree();
            _blendTree.blendType = BlendTreeType.Simple1D;
            _blendTree.blendParameter = _emotion_list[i];
            _blendTree.name = _emotion_list[i];
            var _watingClip = Resources.Load("wait") as AnimationClip;
            var _emotionClip = Resources.Load(_emotion_list[i]) as AnimationClip;
            _blendTree.AddChild(_watingClip);
            _blendTree.AddChild(_emotionClip);
            var _state = rootStatemachine.AddState(_emotion_list[i]);
            _state.motion = _blendTree;
           _states.Add(_state);
        }
        for(int i = 0; i < _emotion_list.Count; i++ ){
            var wait2emotion = new UnityEditor.Animations.AnimatorStateTransition();
            wait2emotion.destinationState = _states[i];
            wait2emotion.hasExitTime = false;
            wait2emotion.AddCondition(AnimatorConditionMode.Greater, 0.2f, _emotion_list[i]);

            var emotion2wait = new UnityEditor.Animations.AnimatorStateTransition();
            emotion2wait.destinationState = waitingState;
            emotion2wait.hasExitTime = false;
            emotion2wait.AddCondition(AnimatorConditionMode.Less, 0.2f, _emotion_list[i]);
            _states[i].AddTransition(emotion2wait);

            var emotion2emotion = new UnityEditor.Animations.AnimatorStateTransition();
            emotion2emotion.hasExitTime = false;
            emotion2emotion.destinationState = _states[i];
            emotion2emotion.duration = 0.5f;
            emotion2emotion.AddCondition(AnimatorConditionMode.Greater, 0.1f, _emotion_list[i]);

            waitingState.AddTransition(wait2emotion);
        }
    }
}

```

### コメント
ステイトはいつもクリップを落とすとできるやつ.

ステイトマシンは階層をもつレイヤー付きのステイトみたいなもの.

BlendTreeはモーション. つまり、アニメーションクリップと同じ扱い.


# その他

## デモ

https://youtu.be/2SSFMmIV7oE

https://youtu.be/oVkz6otUUlM


ループアニメーションの作成

1 . 大体、端と端のキーをそろえる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1353403/5056a946-e979-f7c2-c22e-8762f77a1035.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1353403/2e7c4967-6d78-f236-5eb9-3291c4bc77fb.png)

2 . Very AnimationのEnsure Quaternion Continuityをかける
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1353403/37b3798b-f3a5-7f3b-4811-ae1f26ef4964.png)

3 . 自分のループに対して、 Transition Duraionをかける.

#追記

BlendTreeを使わない版

```CreateAnimaitonController.cs
using UnityEngine;
using UnityEditor;
using UnityEditor.Animations;
using System.Collections;
using System.Collections.Generic;

public class CreateAnimationController : MonoBehaviour
{
    [MenuItem("Window/Create Controller")]
    // Start is called before the first frame update


    static void CreateController()
    {
        List<string> _emotion_list = new List<string>{
        "surprised",
        "excited",
        "angry",
        };

        var controller = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerAtPath("Assets/Resources/AnimationCreationController.controller");

        foreach(var emotion in _emotion_list){
            controller.AddParameter(emotion, AnimatorControllerParameterType.Float);
        }
        var rootStatemachine = controller.layers[0].stateMachine;
        var waitingState = rootStatemachine.AddState("waiting");
        rootStatemachine.defaultState = waitingState;
        waitingState.motion = Resources.Load( "wait") as AnimationClip;

        List<UnityEditor.Animations.AnimatorState> _states = new List<UnityEditor.Animations.AnimatorState>();

        for(int i = 0; i < _emotion_list.Count; i++ ){
            var _watingClip = Resources.Load(""wait") as AnimationClip;
            var _emotionClip = Resources.Load(_emotion_list[i]) as AnimationClip;
            var _state = rootStatemachine.AddState(_emotion_list[i]);
            _state.motion = _emotionClip;
           _states.Add(_state);
        }
        for(int i = 0; i < _emotion_list.Count; i++ ){
            var wait2emotion = new UnityEditor.Animations.AnimatorStateTransition();
            wait2emotion.destinationState = _states[i];
            wait2emotion.hasExitTime = false;
            wait2emotion.AddCondition(AnimatorConditionMode.Greater, 0.8f, _emotion_list[i]);

            var emotion2wait = new UnityEditor.Animations.AnimatorStateTransition();
            emotion2wait.destinationState = waitingState;
            emotion2wait.hasExitTime = false;
            emotion2wait.AddCondition(AnimatorConditionMode.Less, 0.8f, _emotion_list[i]);
            _states[i].AddTransition(emotion2wait);

            var emotion2emotion = new UnityEditor.Animations.AnimatorStateTransition();
            emotion2emotion.hasExitTime = false;
            emotion2emotion.destinationState = _states[i];
            emotion2emotion.duration = 0.5f;
            emotion2emotion.AddCondition(AnimatorConditionMode.Greater, 0.1f, _emotion_list[i]);
            _states[i].AddTransition(emotion2emotion);

            waitingState.AddTransition(wait2emotion);
        }
    }
}

```