Physics & constraints

Semi-Implicit Euler

半陰的オイラー法

速度を先に更新して位置を進める。

1 / 10

Interactive demo

Preparing the demo…

Semi-Implicit Euler

Drag to orbit, Ctrl/⌘ + scroll to zoom. Use two fingers on touch screens.

This explanation is currently available in Japanese.

ひとことで

物体の運動を 1 ステップずつ進めるとき、先に速度を更新し、その新しい速度で位置を進める方法です。位置を先に進める素朴なオイラー法と計算量はまったく同じで、順番を入れ替えただけなのに、軌道が長期間くずれにくく、エネルギーが勝手に増えて発散することもありません。ほとんどのゲームの物理エンジンが、この方法を基本にしています。

ゲームでの使いどころ

  • あらゆる動く物:弾、キャラクターのジャンプ、落下物、パーティクル。「速度に加速度を足し、位置に速度を足す」と書けば、それが半陰的オイラー法です。
  • 物理エンジンの中身:Box2D、PhysX、Bullet、Unity、Unreal の剛体シミュレーションは、基本的にこの方法(または近いもの)で時間を進めています。
  • ばねや軌道の計算:ばね・ダンパーで揺れる物、惑星の公転、振り子など、行ったり来たりする運動で特に差が出ます。

しくみ

時間刻みを Δt\Delta t、加速度を a(x)\mathbf{a}(\mathbf{x}) とします。

陽的(素朴な)オイラー法は、今の値だけを使って両方を進めます。

xn+1=xn+vn Δt,vn+1=vn+a(xn) Δt\mathbf{x}_{n+1} = \mathbf{x}_n + \mathbf{v}_n\,\Delta t, \qquad \mathbf{v}_{n+1} = \mathbf{v}_n + \mathbf{a}(\mathbf{x}_n)\,\Delta t

半陰的オイラー法(シンプレクティック・オイラー法)は、速度を先に更新し、更新後の速度で位置を進めます。

vn+1=vn+a(xn) Δt,xn+1=xn+vn+1 Δt\mathbf{v}_{n+1} = \mathbf{v}_n + \mathbf{a}(\mathbf{x}_n)\,\Delta t, \qquad \mathbf{x}_{n+1} = \mathbf{x}_n + \mathbf{v}_{n+1}\,\Delta t

どちらも 1 ステップの誤差の大きさは同じ(1 次の精度)ですが、誤差のたまり方が違います。

  • 陽的オイラー法は、円運動なら毎ステップ接線方向へまっすぐ踏み出すので、必ず円の外側へずれます。ずれは同じ向きに積み重なり、エネルギーが増え続けて軌道が広がり、最後は飛び去ります。ばねなら揺れが毎回大きくなります。
  • 半陰的オイラー法は、ある時は外へ、ある時は内へと誤差が行ったり来たりし、長い目で見ると打ち消し合います。エネルギーは少し揺れるだけで、増え続けも減り続けもしません。このように「位相空間の面積を保つ」性質をシンプレクティックといい、長時間のシミュレーションで安定する理由になっています。

実装のポイント

  • 力を先に全部集めてから:重力、ばね、推進力など、そのステップで働く力をすべて足し合わせて加速度を出し、それから速度・位置の順に更新します。
  • 時間刻みは一定に:誤差の大きさは時間刻みに比例するので、フレームごとに刻みが変わると結果も変わります。固定タイムステップと組み合わせるのが基本です。
  • 減衰は速度に掛ける:空気抵抗などは、速度の更新時に velocity *= 1 - damping * dt のように入れます。

つまずきやすい点

  • 順番を逆に書いてしまう:位置を先に更新するコードは一見正しく動くので気付きにくいですが、ばねや軌道でじわじわ発散します。「速度が先」と覚えておきます。
  • 硬いばねでは不安定:半陰的オイラー法でも、ばねの固有周期より時間刻みが大きいと発散します(目安は Δt<2/ω\Delta t < 2/\omega)。硬いばねは刻みを細かくする(サブステップ)か、位置ベース物理を使います。
  • 精度が必要なら別の方法:誤差は 1 次なので、弾道の予測線や精密な軌道計算にはルンゲ・クッタ法が向いています。

デモで試すこと

  1. 「惑星の軌道」では、赤(陽的)が 1 周ごとに外へ膨らみ、やがて飛び去ります。青緑(半陰的)は少しゆがみながらも同じ軌道を回り続け、黄色(正確な解)とほぼ重なります。
  2. 右下のグラフは、最初のエネルギーからのずれです。赤は増え続け、青緑は 0 の周りで小さく揺れるだけです。
  3. 「物理の更新回数」を 60 回/秒以上に上げると、陽的オイラー法のずれも小さくなります。刻みを細かくしても根本的な傾向は変わらず、時間をかければ必ず外へずれていきます。
  4. 「ばねの振動」に切り替えると、陽的オイラー法の箱は揺れがどんどん大きくなり、半陰的オイラー法の箱は同じ幅で揺れ続けます。

References

Gaffer On Games — Integration Basics ↗

A general reference for this subcategory.