【Unity】ValveIndexでHumanoidキャラクターの指を動かす

UnityでValveIndexコントローラーの指入力を取り、Humanoid対応モデルの指を動かす方法です

# 本題の前に
* SteamVRは2.0以降を使用します
* SteamVRのセットアップ、ValveIndexコントローラーの指入力を取る方法の説明は以下の記事を参照してください<br>
[UnityでValveIndexコントローラーの指入力を取る](https://qiita.com/ika_yarou/items/5efa5bdfea10269078b5)

# スクリプトの作成

```C#:HoldFinger.cs
using UnityEngine;
using Valve.VR;

public class HoldFinger : MonoBehaviour
{
    private Animator animator;

    private HumanPoseHandler handler;

    private HumanPose humanPose;

    private SteamVR_Action_Skeleton actionLeftSkeleton;

    private SteamVR_Action_Skeleton actionRightSkeleton;

    void Start()
    {
        actionLeftSkeleton = SteamVR_Actions.default_SkeletonLeftHand;

        actionRightSkeleton = SteamVR_Actions.default_SkeletonRightHand;

        animator = GetComponent<Animator>();

        handler = new HumanPoseHandler(animator.avatar, animator.transform);
        // 開始時点のポーズを取得
        handler.GetHumanPose(ref humanPose);
    }

    private void Update()
    {
        // 左親指
        humanPose.muscles[55] = 1 - (2 * actionLeftSkeleton.thumbCurl);
        humanPose.muscles[57] = 1 - (2 * actionLeftSkeleton.thumbCurl);
        humanPose.muscles[58] = 1 - (2 * actionLeftSkeleton.thumbCurl);

        // 左人差し指
        humanPose.muscles[59] = 1 - (2 * actionLeftSkeleton.indexCurl);
        humanPose.muscles[61] = 1 - (2 * actionLeftSkeleton.indexCurl);
        humanPose.muscles[62] = 1 - (2 * actionLeftSkeleton.indexCurl);

        // 左中指
        humanPose.muscles[63] = 1 - (2 * actionLeftSkeleton.middleCurl);
        humanPose.muscles[65] = 1 - (2 * actionLeftSkeleton.middleCurl);
        humanPose.muscles[66] = 1 - (2 * actionLeftSkeleton.middleCurl);

        // 左薬指
        humanPose.muscles[67] = 1 - (2 * actionLeftSkeleton.ringCurl);
        humanPose.muscles[69] = 1 - (2 * actionLeftSkeleton.ringCurl);
        humanPose.muscles[70] = 1 - (2 * actionLeftSkeleton.ringCurl);

        // 左小指
        humanPose.muscles[71] = 1 - (2 * actionLeftSkeleton.pinkyCurl);
        humanPose.muscles[73] = 1 - (2 * actionLeftSkeleton.pinkyCurl);
        humanPose.muscles[74] = 1 - (2 * actionLeftSkeleton.pinkyCurl);

        // 右親指
        humanPose.muscles[75] = 1 - (2 * actionRightSkeleton.thumbCurl);
        humanPose.muscles[77] = 1 - (2 * actionRightSkeleton.thumbCurl);
        humanPose.muscles[78] = 1 - (2 * actionRightSkeleton.thumbCurl);

        // 右人差し指
        humanPose.muscles[79] = 1 - (2 * actionRightSkeleton.indexCurl);
        humanPose.muscles[81] = 1 - (2 * actionRightSkeleton.indexCurl);
        humanPose.muscles[82] = 1 - (2 * actionRightSkeleton.indexCurl);

        // 右中指
        humanPose.muscles[83] = 1 - (2 * actionRightSkeleton.middleCurl);
        humanPose.muscles[85] = 1 - (2 * actionRightSkeleton.middleCurl);
        humanPose.muscles[86] = 1 - (2 * actionRightSkeleton.middleCurl);

        // 右薬指
        humanPose.muscles[87] = 1 - (2 * actionRightSkeleton.ringCurl);
        humanPose.muscles[89] = 1 - (2 * actionRightSkeleton.ringCurl);
        humanPose.muscles[90] = 1 - (2 * actionRightSkeleton.ringCurl);

        // 右小指
        humanPose.muscles[91] = 1 - (2 * actionRightSkeleton.pinkyCurl);
        humanPose.muscles[93] = 1 - (2 * actionRightSkeleton.pinkyCurl);
        humanPose.muscles[94] = 1 - (2 * actionRightSkeleton.pinkyCurl);

        // ポーズを設定
        handler.SetHumanPose(ref humanPose);
    }
}
```
# 使い方
HumanoidキャラクターのAnimatorと同じ階層に、先ほど作成したスクリプト「HoldFinger.cs」をAddComponentします

ゲームを再生してValveIndexコントローラーを握ると、コントローラーを握った指の形に合わせてHumanoidキャラクターの指が動きます
![yubi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567642/d07cdac2-6a3e-617a-8117-274b0f3efa9f.png)

## 微調整
Vroidなど、モデルによっては親指の付け根が伸びたり、小指～人先し指の第1関節が曲がりすぎることがあります
![yubi2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567642/e7396a34-90c1-79f6-c4a7-13270b016d3a.png)
HumanoidリグのConfigureで直す方法もありますが、ここではスクリプトから調整します

```C#
        // 左親指
        //humanPose.muscles[55] = 1 - (2 * actionLeftSkeleton.thumbCurl); // 親指の第3関節を曲げない
        humanPose.muscles[57] = 1 - (2 * actionLeftSkeleton.thumbCurl);
        humanPose.muscles[58] = (1 - (2 * actionLeftSkeleton.thumbCurl))/2; // 指の第1関節の曲がる量を半分にする

        // 左人差し指
        humanPose.muscles[59] = 1 - (2 * actionLeftSkeleton.indexCurl);
        humanPose.muscles[61] = 1 - (2 * actionLeftSkeleton.indexCurl);
        humanPose.muscles[62] = (1 - (2 * actionLeftSkeleton.indexCurl)) / 2;

        // 左中指
        humanPose.muscles[63] = 1 - (2 * actionLeftSkeleton.middleCurl);
        humanPose.muscles[65] = 1 - (2 * actionLeftSkeleton.middleCurl);
        humanPose.muscles[66] = (1 - (2 * actionLeftSkeleton.middleCurl)) / 2;

        // 左薬指
        humanPose.muscles[67] = 1 - (2 * actionLeftSkeleton.ringCurl);
        humanPose.muscles[69] = 1 - (2 * actionLeftSkeleton.ringCurl);
        humanPose.muscles[70] = (1 - (2 * actionLeftSkeleton.ringCurl)) / 2;

        // 左小指
        humanPose.muscles[71] = 1 - (2 * actionLeftSkeleton.pinkyCurl);
        humanPose.muscles[73] = 1 - (2 * actionLeftSkeleton.pinkyCurl);
        humanPose.muscles[74] = (1 - (2 * actionLeftSkeleton.pinkyCurl)) / 2;

        // 右親指
        //humanPose.muscles[75] = 1 - (2 * actionRightSkeleton.thumbCurl);
        humanPose.muscles[77] = 1 - (2 * actionRightSkeleton.thumbCurl);
        humanPose.muscles[78] = 1 - (2 * actionRightSkeleton.thumbCurl);

        // 右人差し指
        humanPose.muscles[79] = 1 - (2 * actionRightSkeleton.indexCurl);
        humanPose.muscles[81] = 1 - (2 * actionRightSkeleton.indexCurl);
        humanPose.muscles[82] = (1 - (2 * actionRightSkeleton.indexCurl)) / 2;

        // 右中指
        humanPose.muscles[83] = 1 - (2 * actionRightSkeleton.middleCurl);
        humanPose.muscles[85] = 1 - (2 * actionRightSkeleton.middleCurl);
        humanPose.muscles[86] = (1 - (2 * actionRightSkeleton.middleCurl)) / 2;

        // 右薬指
        humanPose.muscles[87] = 1 - (2 * actionRightSkeleton.ringCurl);
        humanPose.muscles[89] = 1 - (2 * actionRightSkeleton.ringCurl);
        humanPose.muscles[90] = (1 - (2 * actionRightSkeleton.ringCurl)) / 2;

        // 右小指
        humanPose.muscles[91] = 1 - (2 * actionRightSkeleton.pinkyCurl);
        humanPose.muscles[93] = 1 - (2 * actionRightSkeleton.pinkyCurl);
        humanPose.muscles[94] = (1 - (2 * actionRightSkeleton.pinkyCurl)) / 2;
```


![yubi3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567642/6728537d-6a26-7378-277b-09b794bb62e6.png)
まだ少し不格好ですが、調整前よりキレイに指が曲がります

# 参考
Unityでスクリプトから、Animatorコンポーネントの「Chest-Twist」などの値を取得する方法
https://teratail.com/questions/168728

【Unity】スクリプトからキャラクターのボーンを制御する準備 (備忘録)
https://qiita.com/Nekomasu/items/8884b8584bfc191582d4