【Unity】モーションに合わせていい感じに移動できるAnimatorのTarget Matching

UnityのAnimatorのTarget Matchingについてです。

Unity2018.3.1

どんな時に使う機能?

例えば今こんな感じのジャンプモーションがあるとします。

f:id:halya_11:20190213002742g:plain

そしてこのジャンプモーションでこの台に飛び乗ることを考えます。

f:id:halya_11:20190213002858p:plain

もちろん位置をスクリプトで制御してもいいのですが、その場合には

  1. ジャンプモーションの足が床から離れるタイミングを検知
  2. そのタイミングで移動を開始
  3. ジャンプモーションの着地までの時間を計算
  4. 着地までの時間でうまく移動を完了させる

といった面倒な処理が必要です。
これをある程度簡単にやってくれるのがTarget Matchingです。

f:id:halya_11:20190213003404g:plain

使い方

Target Matchingはスクリプトでこんな感じに制御します。

using System.Collections.Generic;
using UnityEngine;

public class Example : MonoBehaviour 
{
    [SerializeField]
    private List<Transform> _jumpTargets;
    [SerializeField]
    private float _startNormalizedTime;
    [SerializeField]
    private float _endNormalizedTime;

    private Animator _animator;
    private int _jumpStateHash;
    private int _currentTargetIndex = -1;
    private MatchTargetWeightMask _mask;

    void Start ()
    {
        _animator = GetComponent<Animator>();
        _jumpStateHash = Animator.StringToHash("Jump");
        _mask = new MatchTargetWeightMask(Vector3.one, 1f);
    }
    
    void Update ()
    {
        // Jキーでジャンプ状態に遷移
        if(Input.GetKeyDown(KeyCode.J)) {
            _animator.SetTrigger("jump");
            if (_currentTargetIndex < _jumpTargets.Count - 1) {
                _currentTargetIndex++;
            }
        }

        // ジャンプ状態中はMatchTargetを呼ぶ
        if (_animator.GetCurrentAnimatorStateInfo(0).shortNameHash == _jumpStateHash) {  
            _animator.MatchTarget
            (
                _jumpTargets[_currentTargetIndex].position
                , _jumpTargets[_currentTargetIndex].rotation
                , AvatarTarget.LeftFoot
                , _mask
                , _startNormalizedTime
                , _endNormalizedTime
            );
        }
    }
}

ポイント二点です。

一点目はジャンプ中にUpdateでAnimator.MatchTarget()を呼ぶことです。
引数にはジャンプ先のpositionとrotation、着地に使う部位などを渡します。

二点目はこの引数に移動を始める時間と着地する時間を与えることです。
この時間は正規化されたモーションの時間です。
これはアニメーションファイルのプレビューを見ながら手動で調整します。

f:id:halya_11:20190213004223g:plain

結果

適当にオブジェクトを置いて再生するとこんな感じの結果が得られます。

f:id:halya_11:20190213004352g:plain

良い感じに移動できています。

Humanoidでしか使えない

AvatarTargetとか使ってるしHumanoidしか使えないのかな、と思いGenericにして試してみました。

f:id:halya_11:20190213004836g:plain

やはりGenericではTarget Matching動作しないようです。
マニュアルには特に表記はないですが、まあ当然ということでしょうか。

参考

docs.unity3d.com