Version: 2023.1
言語: 日本語
ターゲットマッチング
ルートモーションの仕組み

IK

ほとんどのアニメーションは、スケルトンのジョイントを回転させ事前に決められた値に変更して作られます。子ジョイントの位置は、親の回転にもとづいて変化します。このため一連のジョイントの終了点は、角度および含まれる個々のジョイントの相対位置によって決定されます。このスケルトンのポージング手法は フォワードキネマティクス と呼ばれます。

ただし、ジョイントのポージングを行うタスクを別の視点からとらえることも、しばしば役に立ちます。例えば、空間で特定の点を決めてそこから逆算し、終了点が選択した位置になるように有効な方向にジョイントを向かせます。この方法は、選択した位置のオブジェクトをキャラクターにタッチさせたり、平らでない地面にキャラクターの足をつける、ということをする場合に役立ちます。このアプローチは インバースキネマティックス (IK )と呼ばれ、正しく設定されたアバターによる ヒューマノイドキャラクターの Mecanim でサポートされます。

キャラクターの IK を設定するには、通常は、キャラクターが相互作用するオブジェクトがシーンにあり、特に以下のような Animator 関数から IK を設定します。 SetIKPositionWeight, SetIKRotationWeight, SetIKPosition, SetIKRotation, SetLookAtPosition, bodyPosition, bodyRotation

上の画像で、キャラクターは円筒状のオブジェクトを握っています。どのようにしてこれを実現するのでしょうか。

まず、有効なアバターを持ったキャラクターを準備します。

次に、キャラクタのアニメーションを少なくとも 1 つ含む Animator Controller を作成します。次に、Animator ウィンドウのレイヤーペインで、レイヤーの歯車の設定アイコンをクリックし、コンテキストメニューの IK Pass チェックボックスを有効にします。

デフォルトレイヤーの IK Pass チェックボックスを設定
デフォルトレイヤーの IK Pass チェックボックスを設定

キャラクターの Animator コンポーネントに Animator Controller が割り当てられていることを確認してください。

次に IK を実際に処理するスクリプトをアタッチします。仮にそれを IKControl と呼びましょう。このスクリプトが、キャラクターの右手の IK ターゲットと、持っているオブジェクトを見ているような視線のターゲット位置を設定します。

using UnityEngine;
using System;
using System.Collections;

[RequireComponent(typeof(Animator))]

public class IKControl : MonoBehaviour {

    protected Animator animator;

    public bool ikActive = false;
    public Transform rightHandObj = null;
    public Transform lookObj = null;

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

    // IK 計算のためのコールバック
    void OnAnimatorIK()
    {
        if(animator) {

            // IK がアクティブなら、位置と回転を直接目的地に設定します。
            if(ikActive) {

                //割り当てられていいる場合は、ルックターゲット位置を設定します 
                if(lookObj != null) {
                    animator.SetLookAtWeight(1);
                    animator.SetLookAtPosition(lookObj.position);
                }    

                // 割り当てられている場合は、右手のターゲット位置と回転を設定します
                if(rightHandObj != null) {
                    animator.SetIKPositionWeight(AvatarIKGoal.RightHand,1);
                    animator.SetIKRotationWeight(AvatarIKGoal.RightHand,1);  
                    animator.SetIKPosition(AvatarIKGoal.RightHand,rightHandObj.position);
                    animator.SetIKRotation(AvatarIKGoal.RightHand,rightHandObj.rotation);
                }        

            }

            //IK がアクティブでない場合は、手と頭の位置と回転を元の位置に戻します
            else {          
                animator.SetIKPositionWeight(AvatarIKGoal.RightHand,0);
                animator.SetIKRotationWeight(AvatarIKGoal.RightHand,0);
                animator.SetLookAtWeight(0);
            }
        }
    }    
}


キャラクターの手を円筒オブジェクトの内部にめりこまずに、その中心 (円筒のピボットポイント) に置くために、空の子オブジェクト (この例では Cylinder Grab Handle というオブジェクト) を配置し、手を円筒の上に置き、それに沿って回転させます。その時、手はこの子オブジェクトをターゲットにします。

空の ゲームオブジェクト が IK target の役割を果たすので、手はシリンダーオブジェクトの上に正しく置かれる
空の ゲームオブジェクト が IK target の役割を果たすので、手はシリンダーオブジェクトの上に正しく置かれる

ですから、この Cylinder Grab Handle ゲームオブジェクトを IKControl スクリプトの Right Hand Obj プロパティとして割り当てます。

この例では、視線のターゲットを円筒に設定します。そのため、握り手が下の方にある場合でも、キャラクターは直接オブジェクトの中心を見ます。

再生モードにすると、IK が動き出します。 Ik Active チェックボックスをクリックすると、キャラクターがオブジェクトを握ったり離したりするのを見ることができます。再生モードで円筒をいろいろ動かして、腕や手がオブジェクトに合わせて動くのを確認してみましょう。

ターゲットマッチング
ルートモーションの仕組み