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

IK

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

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

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

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

まず、有効なアバターを持ったキャラクターから始めます。

次に、そのキャラクター用のアニメーションを少なくとも 1 つ含んだ Animator Controller を作成します。それから Animator ウィンドウの Layers ペインでレイヤー設定の歯車アイコンをクリックし、表示されたメニューの 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 のターゲットの役割を果たすので、手は Cylinder オブジェクトの上に正しく置かれます
空のゲームオブジェクトが IK のターゲットの役割を果たすので、手は Cylinder オブジェクトの上に正しく置かれます

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

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

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

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