どうもこんばんは!現実の世界よりこちらの世界が百倍楽しいあしかぺんぎんです!
本日はUnityの続きです!
前回オリジナルの流体計算ができるようになりました。
今回は流体の中で物体を移動させて、流体計算に反映させるいわゆる「連成計算」をやってみたいと思います。
やっと水の中で泳げるんだよ~🐧
それではいってみましょう!
物体とCanvasの座標変換
とりあえず前回の流体計算のCanvasに壁と物体(あしぺん君)を設置してみました。
以下は左側から右側に流速を与えたときの様子になります。
より水っぽくするためにベースの色を水色にしてみました。
当然何もコードを変えていませんので、あしぺん君は動かないし、流体にもなんの影響も与えられません。
そこで、流体と物体の相互作用を計算するコードを付け加えました。こちらのLaddのモデルを参考にしました。
ただし、これだけではだめです。というかコードを付け加える際に重要なことに気が付きました。
物体の位置とCanvas上の位置が違う!ということです。
今回の重要なポイントはここにありました。
座標の違い
流体の計算はCanvasをメッシュに切ってメッシュごとに行っています。
これの中に物体を考慮するためにはまず物体がCanvasのどのメッシュにあるのかを知る必要があります。イメージは以下のような感じです。
今回はここで言う物体が存在するメッシュ(a, b)を知りたいです。
Canvasの幅と高さはwidthとheightで設定してRect TransformでPosを設定できるためCanvas上の各メッシュの座標は把握できます。
さらに物体(あしぺん君)の座標は物体のTransformから把握できます。
そのため、物体の座標がどの位置のメッシュに位置するかは簡単だろ(鼻ほじ~)と思っていました。
しかし、これが大きな落とし穴でした。
例えば物体をCanvasの左下に配置します。このときCanvasのRaw imageのwidthとheightを500と150に設定しました。以下のようになります。
このとき物体のTransformのPositionを見てみましょう。
「??」。私の見立てではCanvasのPositionが(0, 0)でwidthが500なのでx座標が半分の-250、y座標がheightが150なので半分の-75になる予定でした。
しかし結果はx座標が-41、y座標が-11.8で全く違う数値になっています。
この原因は物体とCanvasで座標系が異なるというところにあるみたいです。
物体の座標は「ワールド座標」、Canvasの座標は「スクリーン座標」という別々の座標があるみたいです。
- ワールド座標・・・3D空間の座標のことを指すみたい。
- スクリーン座標・・・解像度に一致するみたい。マウスで取得する座標はこっちらしい。
- ビューポート座標・・・スクリーン座標を0~1にしたものみたい。
よって物体のワールド座標をまずスクリーン座標に変換する必要があります。
座標の変換
変換は一行で可能です。
1 2 3 4 5 6 7 8 9 |
//Unity C# public class Water : MonoBehaviour { public GameObject obj; void Start() { obj = GameObject.Find("ashipen");//物体のオブジェクトを取得 Vector3 osp = Camera.main.WorldToScreenPoint(obj.transform.position);//物体のワールド座標からスクリーン座標へ Vector3 endLeft = Camera.main.ScreenToWorldPoint(Vector3.zero);//スクリーン座標からワールド座標へ } } |
上記コードの通り逆にスクリーン座標からワールド座標への変換も可能です。
これで晴れて物体のスクリーン上の座標が取得できメッシュの位置が把握できます。
ちなみにスクリーン座標で使う解像度ですが、以下のようにFileのBuild SettingsからPlayer SettingsのPlayerの中のResolution and PresentationのResolusionのDefault Screen WidthとDefault Screen Heightから設定できます。
私はメッシュが100×30にしましたのでそれの倍数(500×150)にしました。
物体に与える作用力
ここまででコードが正しければ物体と流体の相互影響は計算できたはずです。
流体から受ける力はAddForce()を使いました。
AddForceは物体に継続的に力を与えるものですが、計算式的には力=質量×加速度ですから、計算した力を物体に与えるときはしっかり理解した上でAddForceに値を入力しないと、思った挙動にならないことに注意しないといけませんね。
時間の概念と力や加速度の関係や単位を理解することが如何に重要かを学びました(単に苦労したので記録しておきます)。
計算結果
これで多分うまく計算できるはずですので、先程と同じように左側から流速を与えてみたいと思います。
物体が右に流れていっている様子がわかると思います。
流れるプールの気分だよ~。あとあんまり物体って言うなよ~
続いて物体を操作してみます。
ちょっとわかりにくいかもしれませんが、物体の動きに合わせて流体の計算がされていることがわかります。
まとめ
今回は流体と物体を連成して計算することをやってみました。以下にまとめます。
- 物体とCanvasの座標は異なる。
- 座標の変換は1行で可能
- 力の与え方は単位等に注意する
今後はもうすこし見た目をそれっぽくしたいのと、ゲームっぽい要素も追加していきたいなどを考えています。
結構苦労したけどまま思っていたことができて満足です!
参考サイト
- Ladd AJC (1994) Numerical simulations of particulate suspensions via a discretized Boltzmann equation. Part 1 Theoretical foundation. J Fluid Mech 271:285–309.
- Ladd AJC (1994) Numerical simulations of particulate suspensions via a discretized Boltzmann equation. Part 2. Numerical results. J Fluid Mech 271:311–339.
- Unity】 Rigidbodyの移動方法
- UnityのCameraが使う3つの座標系
- GameObjectの座標をuGUIの座標に変換する方法【Unity】
- 【Unity開発】uGUIのCanvas Scalerの使い方【ひよこエッセンス】
コメント