Blender と Rigify の使用
カスタムの Playable

Playable API

  • 注意: 現状、 Playable API は “実験的な” 機能であり、 “実験的な” 名前空間に属します。これは、この機能を使って作成したいかなるスクリプトも、 Unity の将来的なバージョンとは互換性が無くなる可能性がある、という事です。

この新しい API は、ツール・エフェクト・その他さまざまなゲームプレイ機構の作成を、データソースをツリー状の形式で整理することによって行えるようにしたものです。

ツリー状の構造のおかげで、複数のデータソースをミックス/ブレンド/修正し、それらを単一の出力から再生することが可能になります。例えば現時点では、 Playable API はアニメーショングラフに対応していますので、 Mecanim をスクリプトで扱うことも可能になります。

現時点で Playable API が対応しているのはアニメーショングラフのみですが、ジェネリック API ですので将来的にはオーディオ、ビデオ、スクリプト、またカスタムの Playable にも対応できる可能性があります。

これらのコード例を表現している Unity のプロジェクトは、こちらでダウンロードできます。 PlayablesExamples.zip

使用方法

ゲームオブジェクトで 1 つのクリップを再生する

下記の MonoBehaviour は、 1 つのノードを持つ簡単なツリーを生成します。このノードが1つのクリップを再生します。

このスクリプト内には新しいタイプのオブジェクトが2つ含まれています。 ひとつは AnimationClipPlayable です。これはジェネリックの AnimationPlayable から派生しており、 アニメーションクリップ をラップすることで、グラフを再生する Playable API の AnimatorControllerPlayable との互換性を持たせるものです。

これらは、Play() 操作によって繋がれます。これは、AnimationClipPlayable をツリーのルートとして設定し、ツリーの出力を「アニメーションプレイヤー」(ここでは アニメーターコントローラー)に接続することによって成されます。この結果ツリーが再生可能になります。

using UnityEngine;
using UnityEngine.Experimental.Director;

[RequireComponent(typeof(Animator))]
public class PlayAnimation : MonoBehaviour
{
    public AnimationClip clip;

    void Start()
    {
        // Wrap the clip in a playable
        var clipPlayable = new AnimationClipPlayable(clip);

        // Bind the playable to the player
        GetComponent<Animator>().Play(clipPlayable);
    }
}

アニメーションブレンドツリーをプログラムで作成する

AnimationMixerPlayable は、2つあるいはそれ以上の AnimationClipPlayable をブレンドしたり、他の(それ自体が他のクリップをブレンドする)ミキサーをブレンドしたりすることができます。 SetInputs() の方式は、下層の AnimationClipPlayable ノードを暗黙的に作成します。(この方式は、AnimationPlayable の配列を直接取得することもあります。)

各クリップのブレンド中のウェイトは、SetInputWeight() で動的に調節できます。ブレンドツリーが生成されて、ひとつのアニメーションから別のアニメーションへ、徐々にスムーズに変化します。

using UnityEngine;
using UnityEngine.Experimental.Director;

[RequireComponent(typeof(Animator))]
public class MixAnimation : MonoBehaviour
{
    public AnimationClip clip1;
    public AnimationClip clip2;

    private AnimationMixerPlayable m_Mixer;

    void Start()
    {
        // Create the mixer and connect it to clips
        // (AnimationClipPlayables are created implicitly)
        m_Mixer = new AnimationMixerPlayable();
        m_Mixer.SetInputs(new[] { clip1, clip2 });

        // Bind the playable graph to the player
        GetComponent<Animator>().Play(m_Mixer);
    }

    void Update()
    {
        // Adjust the weight of each clip in the blend tree based on time
        float weight = (Time.time % 10) / 10;
        Debug.Log(weight);
        m_Mixer.SetInputWeight(0, 1 - weight);
        m_Mixer.SetInputWeight(1, weight);
    }
}

AnimatorController をブレンドする

AnimationClipPlayable が AnimationClip をラップするのと同じように、AnimatorControllerPlayableアニメーターコントローラー をラップできます。これによって、別の AnimationPlayable とブレンドさせることが可能になります。

using UnityEngine;
using UnityEngine.Experimental.Director;

[RequireComponent(typeof(Animator))]
public class BlendAnimatorController : MonoBehaviour
{
    public AnimationClip clip;
    public RuntimeAnimatorController animController;
    AnimationMixerPlayable mixer;

    void Start()
    {
        // Wrap the clip and the controller in playables
        var clipPlayable = new AnimationClipPlayable(clip);
        var controllerPlayable = new AnimatorControllerPlayable(animController);
        mixer = new AnimationMixerPlayable();
        mixer.SetInputs(new AnimationPlayable[] { clipPlayable, controllerPlayable });

        // Bind the playable graph to the player
        GetComponent<Animator>().Play(mixer);
    }

    void Update()
    {
        // Adjust the weight between the clip and the controller based on time
        float weight = (Time.time % 10) / 10;
        Debug.Log(weight);
        mixer.SetInputWeight(0, 1 - weight);
        mixer.SetInputWeight(1, weight);
    }
}

ツリーのタイミングを手動で制御する

デフォルトでは、ツリーの再生のすべてのタイミングは PlayableController の Play() 方式によって制御されています。ただし、より詳細に制御したい場合は、Playable のローカルタイムを具体的に設定することも可能です(ローカルタイムは子ノードに伝播されます)。例えばこの参考例では、再生を一時停止し、キーボードの矢印を使って手動でアニメーションを早送り・巻き戻ししています。

using UnityEngine;
using UnityEngine.Experimental.Director;

[RequireComponent(typeof(Animator))]
public class PlayWithTimeControl : MonoBehaviour
{
    public AnimationClip clip;

    private Playable root;
    private const float speedFactor = 1f;

    void Start()
    {
        root = new AnimationClipPlayable(clip);

        // Bind the playable to the player
        GetComponent<Animator>().Play(root);

        root.state = PlayState.Paused;
    }

    void Update()
    {
        // Control the time manually based on the input
        float horizontalInput = Input.GetAxis("Horizontal");
        root.time += horizontalInput * speedFactor * Time.deltaTime;
    }
}

ツリーの再生状態を制御する

上記と同様、ツリーの状態あるいはブランチも、Playable.state のパラメーターを調整して設定できます。状態はノードのすべての子に(子のそれ以前の状態がどうであったかに関わらず)伝播されます。(【注】子ノードを手動で一時停止しているときに親を Playing 状態にすると、子も Playing 状態になります。)

サンプルプロジェクト

これらのコード例を表現している Unity のプロジェクトは、こちらでダウンロードできます。 PlayablesExamples.zip

Blender と Rigify の使用
カスタムの Playable