FinalIKを使用したVRMアバターの自然な歩行を実現する方法

# はじめに
[以前の記事](https://qiita.com/4sk/items/67612e2191291da7dbec)で，Photonを用いたマルチプレイ対応のアバターシステムを紹介しましたが，アバターの歩き方がかなり不自然でした．
VRIKのパラメータをいじることで多少はましになると思いますが，アニメーションを用いてよりよくする方法を紹介します．

# 開発環境
開発環境は以前の記事と同じです．Oculus Linkを使用して開発を行っていますが，Oculus Integrationが使えれば問題ないかと思います．（他の環境でためしたことないのでわかりませんが）

- Windows10
- Oculus Link対応GPU搭載PC
- Unity version: 2021.3.26f1

# 目次
[1. 完成イメージ](#完成イメージ)
[2. 前提条件](#前提条件)
[3. Animationのインストール](#animationのインストール)
[4. Animatorの作成](#animatorの作成)
[5. Animationを制御するScriptの作成](#animationを制御するscriptの作成)
[6. コンポーネントのアタッチ](#コンポーネントのアタッチ)
[7. おわりに](#おわりに)

# 完成イメージ
![avatar_walk_animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348679/9d849f0a-f526-6098-73bd-b58beefedfb5.gif)

# 前提条件
Oculus integrationやVRMアバターの導入や，VRIKの設定等は，以前の記事などを参考にしてください．
次のような動きができれば大丈夫かと思います．

![zonbieAvatar.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348679/0259a6a9-b0b2-0f6e-b9ec-d463535a46ca.gif)

# Animationのインストール
今回は[Basic Motions FREE](https://assetstore.unity.com/packages/3d/animations/basic-motions-free-154271)をUnity Asset Storeからダウンロードします．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348679/e55f391a-0637-bde8-35ef-4909a05bc004.png)

# Animatorの作成
## Animationの配置
`AvatarWalk`というAnimatorを作成します．
まず，以下のように先ほどダウンロードしたアニメーションを配置して，遷移を作成します．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348679/77c3e778-60a2-9a75-53b0-329b0ab09898.png)

walkF,walkB,walkR,walkLは，`\Assets\Kevin Iglesias\Basic Motions\Animations\Movement\Basic Motions@Walk01.fbx`のAnimationを使用しており，その対応は以下のようになっています．
- `walkF` -> `BasicMotions@Walk01 - Forwards`
- `walkB` -> `BasicMotions@Walk01 - Backwards`
- `walkR` -> `BasicMotions@Walk01 - Right`
- `walkL` -> `BasicMotions@Walk01 - Left`

## パラメータの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348679/b0306444-45bf-a81a-2979-bd1192fd043d.png)

Parametersから，+をおして，Triggerを選択します，
今回は画像の中で`stop`，`walkF`，`walkB`，`walkR`，`walkL`の4つ用います．

## 遷移の作成
まず，上画像のような遷移を作成し，全ての遷移で`Has Exit Time`のチェックを外してください．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348679/81e39773-c479-0885-7d94-8cf5619a5830.png)
また，それぞれのConditionは以下の通りです．（遷移先の名前のParameterを設定すればOKです）
- stop -> walkF : `walkF`
- walkF -> stop : `stop`
- stop -> walkB : `walkB`
- walkB -> stop : `stop`
- stop -> walkR : `walkR`
- walkR -> stop : `stop`
- stop -> walkR : `walkR`
- walkR -> stop : `stop`

# Animationを制御するScriptの作成
次のスクリプトを作成します．
```AvatarAnimationController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AvatarAnimationController : MonoBehaviour
{
    private Animator controller;

    // Start is called before the first frame update
    void Start()
    {
        controller = this.GetComponent<Animator>();
        ResetAnimation();
        controller.SetTrigger("stop");
    }

    void ResetAnimation()
    {   
        controller.ResetTrigger("walkF");
        controller.ResetTrigger("walkB");
        controller.ResetTrigger("walkR");
        controller.ResetTrigger("walkL");
        // controller.ResetTrigger("stop");
    }

    // Update is called once per frame
    void Update()
    {
        // 前進Animation
        if (OVRInput.Get(OVRInput.Button.PrimaryThumbstickUp, OVRInput.Controller.LTouch)){
            ResetAnimation();
            controller.SetTrigger("walkF");
        }

        // 後退Animation
        if (OVRInput.Get(OVRInput.Button.PrimaryThumbstickDown, OVRInput.Controller.LTouch)){
            ResetAnimation();
            controller.SetTrigger("walkB");
        }

        // 右横歩き
        if (OVRInput.Get(OVRInput.Button.PrimaryThumbstickRight, OVRInput.Controller.LTouch)){
            ResetAnimation();
            controller.SetTrigger("walkR");
        }

        // 左横歩き
        if (OVRInput.Get(OVRInput.Button.PrimaryThumbstickLeft, OVRInput.Controller.LTouch)){
            ResetAnimation();
            controller.SetTrigger("walkL");
        }

        // idle状態
        if (OVRInput.GetUp(OVRInput.Button.PrimaryThumbstickUp, OVRInput.Controller.LTouch)
            || OVRInput.GetUp(OVRInput.Button.PrimaryThumbstickDown, OVRInput.Controller.LTouch)
            || OVRInput.GetUp(OVRInput.Button.PrimaryThumbstickRight, OVRInput.Controller.LTouch)
            || OVRInput.GetUp(OVRInput.Button.PrimaryThumbstickLeft, OVRInput.Controller.LTouch)
        ){
            ResetAnimation();
            controller.SetTrigger("stop");
        }

    }
}

```

# コンポーネントのアタッチ
最後に，今まで作成したアニメーター，スクリプトをアタッチします．
アバターとして用いたいVRMアバターの`Animator`コンポーネントのControllerを先ほど作成した`AvatarWalk`とします．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348679/db6b52d5-2cbd-5c59-f626-841a3784d295.png)
また，`Avatar Animation Controller`もアタッチしましょう．（先ほど作成したスクリプトです．）

また，`VRIK`コンポーネントもの`Locomotion`内の`Weight`を0にしましょう．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348679/e4db8ead-8b9c-5d8c-0dbd-fe7bb078c33d.png)

<font color="Red">これで完成です！！！</font>

# おわりに
今回は，以前作成したアバターシステムのアップデートを行いました．
導入は簡単かと思うので参考にしてみてください．