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

IK

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

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

キャラクターの IK をセットアップするためには、通常はシーンに相互作用をさせたいオブジェクトがあり、キャラクターの IK をスクリプトを通じて、具体的には次のような Animator 関数を通じて、セットアップします。 SetIKPositionWeightSetIKRotationWeightSetIKPositionSetIKRotationSetLookAtPositionbodyPositionbodyRotation

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

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

次に、そのキャラクター用のアニメーションを少なくとも 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 オブジェクトの上に正しく置かれます

この “grab handle” ゲームオブジェクト は IKControl スクリプトの “Right Hand Obj” プロパティーとしてアサインします。

この例では、視線ターゲットが円筒オブジェクト自体に設定されているので、キャラクターの手が円筒を持つ位置に関係なくキャラクターは円筒オブジェクトの中心をまっすぐ見ています。

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

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