Water, terrain & plants

Buoyancy

浮力

水に浸かった物体へ上向きの力を与える。

7 / 10

Interactive demo

Preparing the demo…

Buoyancy

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

This explanation is currently available in Japanese.

ひとことで

水に沈んだ部分の体積に応じて、物体に上向きの力(浮力)を加える仕組みです。「押しのけた水の重さだけ浮かされる」というアルキメデスの原理そのものですが、ゲームでは物体の中にいくつかの測定点を置き、点ごとに別の場所で力を加えることで、浮き沈みだけでなく、傾いた物が起き上がり、波に合わせて揺れる動きまで作ります。

ゲームでの使いどころ

  • 船やボート:波に合わせて上下し、船首と船尾が交互に持ち上がる。荷物を積むと沈み込み、偏って積むと傾く。
  • 浮かぶ物・沈む物:木箱や樽は浮き、鉄の箱は沈む。水に落とした物がしぶきを上げて一度沈み、浮かび上がってくる。
  • 泳ぎやダイビング:キャラクターの浮き具合、水中で重い装備を持つと沈む、といったゲーム性にも使えます。
  • パズル:浮き輪で荷物を浮かせる、水位を上げて足場を浮かせる、など。

しくみ

アルキメデスの原理:水中の物体は、押しのけた水の重さと同じ大きさの上向きの力を受けます。

F=ρ水 g V水中F = \rho_{\text{水}}\, g\, V_{\text{水中}}

物体の密度が水(1000 kg/m³)より小さければ、一部だけ沈んだ所で重力と釣り合って浮きます。例えば密度 600 kg/m³ の木箱は、体積の 60% が沈んだ所で止まります。水より重ければ、全部沈んでも浮力が重力に勝てず、沈んでいきます。

ゲームでは、物体の沈んだ体積を正確に求める代わりに、次のように近似します。

  1. 物体を小さな区画に分ける:例えば直方体を 3×3×33\times3\times3 に分け、各区画の中心に測定点を置きます。
  2. 点ごとに水面と比べる:その点の真上の水面の高さ(波の式から求める)と比べ、どれだけ沈んでいるかを 0〜1 の割合にします。
  3. 点ごとに力を加える:各点に「区画の体積 × 沈んだ割合」ぶんの浮力を、その点の位置に加えます。重心からずれた位置に力がかかるので、回転させる力(トルク)も生まれます。
τ=∑i(pi−c)×Fi\boldsymbol{\tau} = \sum_i (\mathbf{p}_i - \mathbf{c}) \times \mathbf{F}_i

片側が沈むとその側の浮力が強くなるので、物体は水平に戻ろうとします。波の斜面では、斜面の高い側の点ほど深く沈むので、物体が波に沿って傾きます。

  1. 水の抵抗を加える:水中の点には、その点の速度と逆向きの抵抗を加えます。これがないと、物体はばねのように上下に揺れ続けます。回転による点の速度(ω×r\boldsymbol{\omega} \times \mathbf{r})も含めると、横揺れも自然に収まります。

実装のポイント

  • 物理エンジンと組み合わせる:Unity や Unreal なら、各点で AddForceAtPosition を呼ぶだけで、回転は物理エンジンが計算してくれます。
  • 水面の高さは描画と同じ式で:ゲルストナー波なら CPU で同じ式を評価します。GPU の FFT 海洋を使う場合は、高さの画像を CPU に読み戻すか、同じ計算を CPU 側でも低解像度で行います。
  • 時間刻みを細かく:浮力はばねのように働くので、軽い物体ほど固い「ばね」になります。固定タイムステップで 1 フレームを数ステップに分けると安定します。
  • 測定点の数:大きな船は船体の形に沿って 10〜数十点、小さな物は 4〜8 点程度で十分です。

つまずきやすい点

  • 点が 1 つだけ:重心の 1 点だけで浮力を測ると、浮き沈みはしますがトルクが生まれず、傾きも起き上がりもしません。
  • 沈んだ割合が 0 か 1 か:点が水面の上か下かの 2 択にすると、点が水面を横切るたびに力が急に変わり、物体ががたがた震えます。区画の高さの中で割合をなめらかに変えます。
  • 抵抗がない、または強すぎる:抵抗がないと延々と揺れ、強すぎると水あめの中のように動きが鈍くなります。重い物ほど抵抗の効きが弱くなるよう、区画の体積に比例させます。

デモで試すこと

  1. 左下の数値は、それぞれの物体が体積の何割沈んでいるかです。密度 320 の小舟は約 3 割、600 の木箱は約 6 割沈み、2400 の鉄の箱は完全に沈みます。
  2. 「空から落とす」を押すと、傾いた姿勢で落ちた物体が一度深く沈んでから浮かび上がり、水平に起き上がる様子が見られます。
  3. 「浮力を測る点」を「中心の 1 点」にすると、物体は波に合わせて上下はしますが、傾きが変わらなくなります。3×3×3 点に戻すと、波の斜面に沿って揺れます。
  4. 「水の抵抗」を 0 にすると、いつまでも上下に揺れ続けます。「波の高さ」を上げると、小舟が波の斜面で大きく傾きます。

References

GPU Gems — Effective Water Simulation ↗

A general reference for this subcategory.