【Unity】Animation Riggingでキャラを自然に振り向かせる

投稿者: | 2023-11-11

「Animation Rigging」パッケージを使って、敵キャラに体ごと自然にプレイヤーの方を振り向かせてみました。

Animation Riggingはアニメーションリグやコンストレイントによって、動的にアニメーションを変更できます。Animation Riggingはパッケージマネージャーからインストールできます。

Rig BuilderとRigを設定

まず、キャラクターのルート等Animatorコンポーネントを持つゲームオブジェクトにRig Builderコンポーネントを追加します。

その子として空のゲームオブジェクトを作成して、Rigコンポーネントを付けます。

Rig Builderコンポーネントの「Rig Layers」にこのゲームオブジェクトをアタッチします。

顔をプレイヤーの方へ向かせる

Rigゲームオブジェクトの下にコンストレイントをまとめます。まず敵の顔をプレイヤーのカメラの方へ向かせるために「Multi-Aim Constraint」を設定してみます。

Rigゲームオブジェクトの下に空のゲームオブジェクトを作りMulti-Aim Constraintコンポーネントを追加します。

Multi-Aim Constraintコンポーネントの「Constrained Object」にキャラクターの頭のボーンを、Source Objectsにターゲットの空のゲームオブジェクトをアタッチします。

ターゲットはこのゲームオブジェクトの子にしています。

頭のボーンは Y が上で Z が前なので、Aim Axisを -Z にすると、顔をそむけます。

Constrained AxesをY軸のみにして、キャラの頭が真上を向かないようにしています。

X, Y, Z軸をオン
Y軸のみオン

Min LimitとMax Limitでは、頭の回転を制限しています。

ターゲットをプレイヤーのカメラの位置に置く

ターゲットのゲームオブジェクトに「Parent Constraint」コンポーネントを付けて、ターゲットをプレイヤーのカメラと同じ位置に置いています。

Sourcesにプレイヤーのカメラが置かれるトランスフォームをアタッチします。「Zero」ボタンを押すと、オフセットがなくなって、ターゲットがソースと同じ位置にきます。

これでキャラの顔だけがプレイヤーの方を向くようになりました。

頭につられて上体を回転させる

顔に合わせてキャラの上半身を少し回転させるために、Rigゲームオブジェクトの下に新しく空のゲームオブジェクトを追加して、「Twist Correction」コンポーネントを付けます。

Twist Correctionコンポーネントの「Twist Nodes」に首と2つの脊椎ボーンをアタッチして、Y軸に沿って回転させます。

ソースのゲームオブジェクトに合わせて各ボーンをどのくらい回転させるかを、右のスライダーで設定できます。プレイモードで確認しながら調節しました。

ソースはこのゲームオブジェクトの子にしています。ソースのゲームオブジェクトに「Parent Constraint」を付けて、「Sources」に頭のボーンをアタッチしています。

これでキャラの上体も回転するようになりました。

コンストレイントの順序を変えると挙動が変わりました。

スクリプトでRigのウェイトを変更

Rigのウェイトが0だとコンストレイントの影響を受けず、キャラが振り向かなくなります。

Rigのウェイトはアニメーションやスクリプトで変更できます。

using System.Collections;
using UnityEngine;
using UnityEngine.Animations.Rigging;
using UnityEngine.InputSystem;

public class RiggingTest : MonoBehaviour
{
    [SerializeField] Rig rig;
    [SerializeField] float turningSpeed = 2f;
    bool isIdling;
    Animator animator;

    void Start()
    {
        animator = GetComponent<Animator>();
    }

    void Update()
    {

        if (Mouse.current.leftButton.wasPressedThisFrame)
        {
            isIdling = !isIdling;

            if (isIdling)
            {
                EnablePlayerLook();

            }
            else
            {
                DisablePlayerLook();
            }
        }

    }


    void EnablePlayerLook()
    {
        animator.SetBool("IsIdling", true);
        // rig.weight = 1f;
        StopAllCoroutines();
        StartCoroutine("IncreaseRigWeight");
    }

    IEnumerator IncreaseRigWeight()
    {

        var weight = rig.weight;
        while(true)
        {
            weight += Time.deltaTime * turningSpeed;

            rig.weight = weight;

            if(weight >= 1f)
            {
                rig.weight = weight;
                yield break;
            }

            yield return null;
        }
    }

    void DisablePlayerLook()
    {
        animator.SetBool("IsIdling", false);
        //rig.weight = 0f;

        StopAllCoroutines();
        StartCoroutine("DecreaseRigWeight");
    }

    IEnumerator DecreaseRigWeight()
    {

        var weight = rig.weight;
        while (true)
        {
            weight -= Time.deltaTime * turningSpeed;

            rig.weight = weight;

            if (weight <= 0f)
            {
                rig.weight = 0f;
                yield break;
            }

            yield return null;
        }
    }
}

コメントを残す

メールアドレスが公開されることはありません。