Teleport
リリース 4.9 において、いくつかのノードに対して Teleport フラグが公開されましたので、ここでこのフラグの機能について詳しく説明したいと思います。
物理オブジェクトを移動させる場合、速度とコリジョンについて考えます。通常、オブジェクトの位置 (または回転) が設定されると、物理エンジンが暗黙の速度を計算し、それを使ってワールド内でオブジェクトを移動させます。これにより、衝突するオブジェクトが正しい速度でバウンスするようになります。
この暗黙の速度には、キャラクターがシミュレートされたボディに付着していると (馬の尻尾やカンガルーの腹袋)、それも一緒に物理的に前後に揺らしてくれる副次的なエフェクトがあります。ただし、キャラクターを長距離にわたって移動させなければならない場合 (リスポーン時など)、このエフェクトを取り除くこともできます。そのようなケースでは、速度 = 移動距離 / フレーム時間ですから、暗黙の速度値が非常に大きくなってしまいまうからです。
そうならないように、目標位置にオブジェクトを迅速かつ速度を変えずに移動させることができるのが Teleport フラグです。
例
下の例では、シンプルなボールのキャラクターの上に、前後に揺れるようにシミュレートさせたアンテナを付けました。ウォール (といっても箱を積み上げただけですが) を通過してキャラクターをテレポートさせたい場合、アンテナが継承している暗黙の速度値が非常に高いため、通常の SetWorldLocation を使用してもうまくいきません。
Teleport フラグを true に設定するとどうでしょうか。キャラクターは速度を変えずに移動し、しかもアンテナはキャラクターの頭上にぴったり止まっています。
Sweep
Sweep フラグは移動を制限します。例えば、プレイヤーがウォールを通過できないようにするには、Sweep フラグを使って、最初のブロック ボリュームで移動が止まるようにします。Sweep と Teleport は互いに全く依存しないので、両方を組み合わせるとビヘイビアが非常に興味深くなります。
例
この例では、AddActorLocalOffset をフレームごとに呼び出して、移動を表現しています。これを、組み合わせたフラグごとに行って、好きなビヘイビアを表現します。Teleport がオフの場合、慣性によりアンテナが遅れます。Teleport がオンの場合、アンテナはボールの速度と同じ速さで移動します。Sweep がオンの場合、ボールは箱と衝突する前に停止するのが分かります。Sweep がオフの場合、ボールは箱にぶつかって散らして移動します。
ビヘイビアをまとめてみました。
Teleport = False | Teleport = True | |
---|---|---|
Sweep = False |
最終位置はユーザーの指定した位置になります。 速度は最終位置によって変わります。 オブジェクトの衝突は暗黙の速度に反応します。 |
最終位置はユーザーの指定した位置になります。 速度は変わりません。 衝突するオブジェクトは通り抜けるだけになります。 |
Sweep = True |
最終位置は、パスに沿って最初に衝突したオブジェクトによって決定します。 速度は最終位置によって変わります。 Sweep の作用でコリジョンは発生しません。 |
最終位置は、パスに沿って最初に衝突したオブジェクトによって決定します。 速度は変わりません。 Sweep の作用でコリジョンは発生しません。 |
CCD (常時当たり判定)
最初の例を見て、ウォールを通過した時、積み上げられた箱に物理的な反応がなかったのは何故だろうと不思議に感じたかもしれません。箱にぶつかって崩さないようにマップの向こう側へジャンプしたかったことをエンジンは理解していた、ということになります。なぜでしょうか。
それは、それがデフォルトのビヘイビアだったからです。ワールド内でキャラクターを実際に移動させて、途中で反応を計算すると非常に負荷が高くなってしまいます。そこでエンジンは、まずキャラクターを最終位置に配置し、次にコリジョンを確認します。Teleport を使用すれば、衝突するオブジェクトはただ通過します (実際にかかる速度は無視します)。Teleport がオフの場合、衝突するオブジェクトは暗黙の速度で跳ね返ってしまいます。
ただし、常時当たり判定 (CCD) を ON にすれば、このビヘイビアはもちろん変更することができます。CCD は演算処理的には負荷が高いですが、高速な移動を必要とする物理ベースのゲームにはマストです。
Sweep、Teleport、CCD は交互に使用することができます。Teleport を使うと CCD は事実上無視されることにご注意ください。
シミュレートされたオブジェクト
シミュレートされたオブジェクトの速度は物理シミュレーションで操作されます。そのため、シミュレートされたオブジェクト上で行われる移動は暗黙的にテレポートに変わります。さらに、運動学的なオブジェクトをシミュレートする場合には特別な注意が必要です。シミュレートしていないオブジェクトの位置を Teleport を使用せずに設定することを考えてみましょう。フレーム (PostPhysics) の最後がオブジェクトが到達する目標位置になるように、物理エンジンにオブジェクト速度の変更をリクエストします。ただし、ここで急にシミュレート対象オブジェクトを変更すると、目標位置が無視されてしまいます。これは物理シミュレーションの実行タイミングが間に合わなかったために、暗黙の速度が計算できなかったのです。結果、一番最初のリクエストは事実上無視されました。位置を確実に設定するには Teleport を使わなければなりません。
シーン クエリ
一般的なオブジェクトの移動は、(シミュレーション中にオブジェクトを移動する速度を使用する) 物理シミュレーション側で遅くなります。ですが、シーン クエリ (レイキャスト、カプセル スイープなど) では、すぐに移動したように処理されます。一般的なゲームプレイを考えてみると、わざわざこうしている理由に頷ける (のではないか) と思います。
2 つのキャラクター (Player1 と Player2) があるとします。 キャラクターにウォールを通りぬけてほしくないので、Sweep フラグを使います。ここで、2 つのキャラクターを同じ位置に移動させる場合を想像しましょう。Player1 をまず移動させるために、目標位置へカプセル スイープを行います。何もないので、Player1 は前に進んで、物理エンジンに目標位置へ移動するように指示します。今度は Player2 がカプセル スイープを行います。シーン クエリがすぐに位置の変更を確認するので、Player2 のスイープは目標位置にはもう Player1 がいることが分かります。Player2 はパスに沿って移動しますが、Player1 と衝突する前に停止します。
シーン クエリが同じ遅延スキームを物理シミュレーションとして使用すると、Player2 のスイープは Player1 を確認しません (Player1 の位置は実際にはまだ変更していないからです)。Player1 と Player2 は同じ位置となり、望んでいた結果となりました!