こんにちは。ユニティ・テクノロジーズ・ジャパンの高橋です。

今回のエントリは “TIPS” のカテゴリに分類されるものです。このカテゴリでは、Unity を使う上で知っておくと便利なテクニックを紹介していきます。栄えある(?)第1回のエントリは、アニメーションの補間に関するものです。

Unity でカットシーンのデモを作成したことはありますでしょうか? 作成するのはとても簡単です。Unity のシーン上にモデルやカメラをセットアップしたうえで、各々のオブジェクトのアニメーションがしかるべき順序で再生されるようスクリプトを書いてあげれば完成です。

Constant を使ったカーブ複数のカットを繋げることも難しくありません。アニメーションカーブの接線 (tangent) を “Constant” にすれば、非連続的な値の変化を表現できるので、これでカメラの位置や回転をパキっと切り替えてしまえよいのです。あたかもカットが切り替わったように見えるはずです。

しかし実際にこれを試してみると、うまくいかないことが分かると思います。位置 (position) はパキっと切り替わるのですが、回転 (rotation) は補間されてしまうのです。

確認のためのサンプルをこちらに用意してみました。

Web Player で確認 (約32kB)

よく目を凝らして見ると、切り替わりの際に微妙な補間が入ってしまっているのが分かります。画面上にあるスライダー(時間の進む早さが変化します)を使うと、もっとよく分かるでしょう。

どうしてこのような現象が起きてしまうのでしょうか? これは Unity のアニメーションシステムに現状存在している制限のひとつです。Rotation のアニメーションにおいては tangent の設定がうまく適用されないのです。これには様々な理由があるのですが……これ以上語ると愚痴っぽくなってしまうのでやめておきましょう。前向きに回避方法を考えてみることにします!

これを回避するもっとも簡単な方法は、スクリプトを使って余計な回転を切ってしまうことです。私はこれを animation latch と呼ぶことにしました。こんな内容の簡単なスクリプトです。

private var latchRotation : Quaternion;

function OnEnable () {
    latchRotation = transform.localRotation;
}

function LateUpdate () {
    transform.localRotation = latchRotation;
}

スクリプトがイネーブルされると、その瞬間の rotation の値を保存します。そしてスクリプトがディゼーブルされるまでの間、アニメーションの結果をその保存値で上書きするのです。

このスクリプトを Animation と同じゲームオブジェクトに追加したうえで、アニメーションカーブを使ってスクリプトの enabled を操作します。次の図を見てください。

Latch 制御を織り込んだアニメーション

黄色いカーブが rotation を、青いカーブがスクリプトの enabled を表しています。黄色いカーブが非連続的に変化するタイミングで latch を有効にしています。

こうして改善されたサンプルをこちらに置いておきました。

Web Player で確認 (約32kB)

さきほどのサンプルとは違い、カメラがパキっと切り替わっているのが分かります。

この手法は、カメラ以外のアニメーションでも同様に利用できます。アニメーションを DCC ツール上で作成する場合は、適当なダミー joint で latch の状態を表すようにするとよいでしょう。そのうえで、ダミー joint の動きと latch を連動させるためのスクリプトを書き足すのです。

このエントリのサンプルプロジェクトをダウンロード

Keijiro Takahashi