【Unity】RigidbodyのInterpolate(補間)を変えて実験

【Unity】RigidbodyのInterpolate(補間)を変えて実験

Rigidbodyのオブジェクトをカメラで追っていると、若干のカクツキを感じることがあります。

物理演算と画面の描画タイミングは必ずしも一致しておらず、描画時に参照するオブジェクトの位置がずれるためにカクツキが発生します。

そのカクツキ、減らせるんです。そう、Interpolateならね。

今回はそのInterpolateの実例をご紹介。

 

環境

macOS 10.13 High Sierra

Unity2018.1.0f2

4月末にUnity2018が出てたので早速使ってみました。

Rigidbodyについて

Rigidbodyのアタッチ方法や各設定項目の説明は、以下の記事で解説しています。

ざっくり言うと、Unityで物理演算を使うために必要なコンポーネントです。

今回はその中でもInterpolate(補間)がテーマ。

Rigidbodyのパラメータ
Rigidbodyのパラメータ

 

Interpolate(補間)について

Interpolateは日本語訳すると「付け加える」とか「差し挟む」といった感じ。間に入れて補う機能です。

補間の分かりやすい例はExcelの近似曲線です。プロットした点と点から、「この間は多分こんな感じ」って値を予測する機能。

Unity的には、Update()が呼ばれたタイミングでRigidbodyのアタッチされたコンポーネントの位置を計算して画面に表示する機能になってます。

なぜこの機能が必要かと言えば、Update()が呼ばれるタイミングと、物理演算を行うFixedUpdate()が呼ばれるタイミングは必ずしも一致しないため。

Unity2017.4までは、FixedUpdateはデフォルトで1秒間に50回の更新となっています。Unity2018.1からは、デフォルトだとFixedUpdateが1秒間に60回呼ばれるようになりました。いつの間にか変わっててびっくり。

対して、画面の描画に関わるUpdate関数が呼ばれる回数は変動します。

Unityエディタではだいたい60回前後で揺らぎがあり、PC用にビルドしたゲームではPCの性能に大きく依存しますし、モバイルではデフォルトで1秒間に30回呼ばれます。

物理演算の呼ばれる回数と一致していないので、「画面にオブジェクトを描画するよー!」とUnityが気合いを入れていても、参照する位置が前のフレームのものだった、なんてことも起こり得ます。

結果として、マニュアルで言われている『痙攣しているような見た目』が観察されることに。

 

設定項目

RigidbodyのInterpolateで設定できるのは以下の3つ。

  • None
  • Interpolate
  • Extrapolate

『None』は補間が行われない状態です。デフォルトではこれが選択されています。

『Interpolate』は補間が行われ、描画がスムーズになります。補間は直前フレームの速度を使って計算します。こちらは過去の実績に基づいて位置を算出する方法ですね。設定名と設定内容が同じでちょっと紛らわしいかも。

『Extrapolate』を選択した場合も補間が行われますが、こちらは現在の速度から次フレームの位置を予測して補間を行います。『Interpolate』とは逆に未来予測で位置を算出します。

スクリプトリファレンスを見ると、『Interpolate』は『Extrapolate』より反応が遅れることがあるそうな。

上記のUnity Answersを見ると、『Interpolate』の方が計算コストが高く、『Extrapolate』の方は比較的コストが安いようです。ただし、『Extrapolate』は現在の速度から位置を算出するので、変なところに描画されるリスクもあるみたい。

Interpolateの有無でどう変わるか

文字だけだとイメージしにくいかも。

なので、簡単に比較実験をしてみましょ。

用意したボールは以下の3種類。

  • Interpolate : None
  • Interpolate : Interpolate
  • Interpolate : Extrapolate

Interpolateの設定だけ変えて、あとはRigidbodyデフォルトのままにしています。

上記のボールにConstantForceコンポーネントで力を加え続け、どんどん加速させます。その様子をカメラで追いかけて、描画にどのように差が出るか検証します。

追いかける対象のボールは一番手前の『Extrapolate』のボールです。痙攣する見た目の『None』を追いかけてしまうと、カメラも同時に痙攣してしまうので、安定して描画されるものを選択しました。安定という意味では『Interpolate』でも多分大丈夫。

GIFだとあまりにも容量が大きくなりすぎたので、YouTubeに上げました。動画だと白いボールの動きが気持ち悪いことになっているのが見て取れます。

設定を表示するUIはブレているものの、Interpolateを設定しているボール自体は綺麗に表示されます。

 

 

ダイジェストで画面をお送りすると、以下のイメージです。『Interpolate』のボールは若干後ろに、『None』は真ん中くらい、『Extrapolate』はちょっと先にいます。

開始してすぐに位置の差異が
開始してすぐに位置の差異が

 

画面キャプチャだとまともに見えますが、『None』は既にブルブル震えて、どこにいるか怪しい感じです。辛うじて、『Interpolate』と『Extrapolate』の間にはいます。

地面が無くなってもさらに加速
地面が無くなってもさらに加速

 

上記の画面からもう少し時間が経ったもの。『None』は痙攣どころかテレポートで瞬間移動しています。操作キャラがこんな動きしてたらプレイヤーはビビるわぁ。

『Interpolate』と『Extrapolate』の位置にも注目。その計算方法の違いによって、時間経過と共に差が大きくなっています。

『Interpolate』が遅れるというのは、こういう意味でもあるのかも。

かなりの差が出る
かなりの差が出る

 

Interpolateの使い所

描画するタイミングでオブジェクトの位置を補間して計算する必要があることから、Interpolateは結構重い処理だったりします。

なので、Rigidbodyを持つオブジェクト全部でInterpolateしようとすると、パフォーマンスが犠牲になってしまいます。

Interpolateのスクリプトリファレンスに書かれているUnityの推奨では、メインカメラで追う必要のあるオブジェクトのみをInterpolateで滑らかに描画するのが良さげ、とのこと。

つまり主人公となるキャラクターをカメラで追いかける時に、主人公のRigidbodyでInterpolateを有効にして、その他のRigidbodyではInterpolateを無効のままにしておくべし。

カメラで追っている主人公が痙攣していたら、プレイヤーはびっくりしますし。痙攣系主人公。びっくりどころか嫌だわそんなゲーム。

『Interpolate』と『Extrapolate』の選び方ですが、急激な速度変化があるのであれば、『Interpolate』を使った方がいいです。『Extrapolate』は現在の速度から位置を予測するため、速度変化が大きければ思わぬ位置に表示されるリスクがあります。

まとめ

Rigidbodyの設定であるInterpolate(補間)の解説と実例でした。

補間なしだと結構ブレが大きいので、Unityが推奨するように、メインカメラで追いかけるオブジェクトに関してはInterpolateを設定しておいた方がいいです。

     

ゲーム開発の攻略チャートを作りました!

CTA-IMAGE

「ゲームを作ってみたいけど、何から手を付けていいか分からない!」


そんなお悩みをお持ちの方向けに、todoがアプリをリリースした経験を中心に、ゲーム作りの手順や考慮すべき点をまとめたe-bookを作成しました。ゲーム作りはそれ自体がゲームのように楽しいプロセスなので、「攻略チャート」と名付けています。


ゲームを作り始めた時にぶつかる壁である「何をしたら良いのか分からない」という悩みを吹き飛ばしましょう!