【Unity2D】流体計算をして表示させてみよう!

こんにちは!お久しぶりですーどうもあしかぺんぎんです。

3連休の最終日ですがいかがお過ごしでしょうか。

私はUnityでのプログラミングがうまく行かず悩みに悩んだ3連休(実は先週の3連休も)でした。

しかーし!とりあえず納得行く結果ができましたので、紹介したいと思います。

今回はUnityの流体計算です!以前に無料のAsset「NVIDIA Flex for Unity」を用いて流体計算を実施しましたが、今回は自分自身で計算してそれを描画表示させることに挑戦しました。

流体計算には「LBM(格子ボルツマン法)」を用いました。それでは行きましょう!

あしぺん
あしぺん

がんばったんだよ~

格子ボルツマン法とは?

流体計算いろいろ

格子ボルツマン法LBM(Lattice Boltzman Method)と呼ばれる流体計算の手法です。

流体計算と言っても難しいと思いますが、つまりは水の流れを計算するわけです。

水は高いところから低いところへ流れますし、壁があると跳ね返ったりします。

この水の性質を記述した方程式にナビエ・ストークス方程式というものがあります(以下の式)。

ナビエ・ストークス方程式

なんじゃこりゃ!頭の悪い私にはなにかの暗号にしか見えませんが、どうやらこれで水の流れが計算できるみたいです。

といってもこの方程式は一般解(x=○○!みたいなやつ)がまだ求められておらず、ミレニアム懸賞問題に指定されていまして、解くと100万ドルがもらえるみたいです!

まあ私には関係ない話ですね~(鼻ほじ~😃)。とても難しい方程式なのでコンピュータを使って近似して計算するのが一般的です。

流体計算いろいろ

流体計算の種類はいっぱいあります。今回はその中から格子ボルツマン法を選んだわけですが、ゲーム作成に使えそうなものを一部紹介します。

  • 差分法による計算手法・・・領域を一般的に四角のメッシュに分割して計算します。もととなる方程式を差分形式で解く方法です。直感的でわかりやすいです。
  • 粒子法による計算手法・・・流体を粒子(つぶつぶ)で表現して計算します。流体の方程式を解くSPH(Smoothed Particle Hydrodynamics)や粒子の衝突から計算するDEM(
    Distinct Element Method)
    なんかがあります。この間の流体計算はこのDEMの一種だと思います。

とはいえ真面目にコンピュータで計算しようとすると膨大な計算時間とメモリが必要となります。

私が研究者で「流体の挙動をきめ細やかに調べる必要がある!」とかだったらスパコンなんかを使って大量のメモリを消費して計算するのでしょうが、ゲームのエフェクト等に使うのが目的ですので、まあそれっぽい水の動きをリアルタイムに表現できれば良いです。

ゲームの流体計算の方法については色々文献があるみたいですので、こちらに貼っておきます。

格子ボルツマン法を選んだ理由

話がだいぶそれましたが、格子ボルツマン法を選んだ理由ですが答えは単純です。

コードが簡単だからです。コードが簡単かつ相応の精度で流体計算が行えるためです。

コードが簡単ということは記述が楽というだけでなく、計算にかかる時間もそれほど多くないということです。要は楽したかったということです😃😃

2次元だと以下の方程式を解けば良いので非常に楽でした。こういうやつです。

・・・・実際にはこちらのサイトにあるものを参考にしたり、本を読んだりして結構勉強しました😫😫(疲れた・・・)

気づいた方がいるかもしれませんが、上記でナビエ・ストークスを説明しておきながら格子ボルツマン法はナビエ・ストークスを直接計算しているわけではないです。

もとは気体の分子運動論からきていて、粒子の移動と衝突から流体の流れを記述するものです。

詳しくは理解できていませんが、空気を構成する気体の粒子が移動して衝突している現象を格子上で計算して流体の挙動を模擬しているような感じです。気体も流体ですよね。

なので気体分子の速度が従う分布関数を記述するマクスウェル分布と呼ばれるものが方程式のもとになっています。

先程ナビエ・ストークス方程式を直接解いていないと述べましたが、結局この格子ボルツマン法のもとの方程式をしこしこ解いていくと近似されたナビエ・ストークス方程式が現れるみたいです

結局流体の挙動を解いているということですね!すごく面白いです。長々説明してきましたがこれが言いたかっただけです😅😅。

あしぺん
あしぺん

勉強は苦手です

Unityで流体計算+描画

さて、理論の部分はこれくらいにしてこれをUnityに実装したいと思います(これもめちゃくちゃ大変だった;;)。

今回は最終的にうまくいった方法と最後にそれまでの試行錯誤の記録を残したいと思います。

テクスチャーを作成して表示する

参考にしたサイトはこちらです。

今回の考えている流体計算の描画の流れはこんな感じです。

ざっくりした流れ

流体計算の結果を使ってテクスチャーを作成して、それを貼付けるといった流れです。

テクスチャーとは?

  • オブジェクトの質感や見た目を変えるものです。テクスチャーを作ればオブジェクトにドラッグ&ドロップで貼り付ければOK!
あしぺん
あしぺん

僕がいっぱいいるんだよ~

まずHierarchyUICanvasを作成します。

Canvasの作成

その後作成したCanvasを右クリックしUIからRaw imageを選択します。

Raw imageの作成

するとCanvasの中にRaw imageができます。

このCanvasに流体計算の結果を描画します。Raw imageは流体計算の結果を貼り付けるためのコンポーネントです。

続いて今回のキモである流体計算とテクスチャの作成と貼付けのスクリプトを作成します。作成したスクリプトのコードを以下に示します。流体計算のところは結局長いのでそれ以外の部分を載せます。

スクリプトを作成したら、Hierarchy2D ObjectからSpriteを選択してそこに作成したスクリプト(今回は「Water」という名前)をドラッグ&ドロップで関連付けます。

また、SpriteWaterのスクリプトのWaterに(ややこしい)Raw imageを関連付けます。

これで操作は完了です!後は適当に流体計算のパラメータをいじって再生します。

以下の上の動画は初期条件として左側の境界に速度を与えたものと、下の動画は初期条件として領域の中心付近に圧力を与えたものになります。

左側に速度を与えたときの挙動
中心付近に圧力を与えたときの挙動

おおおおおおおおおーーー!

なんとなくそれっぽいのができました。しかもリアルタイムで描画されています。

計算格子としては幅100×高さ75になります。下の方の動画だと少し描画の粗さが目立つような気がします。

そこで格子数を倍の幅200×高さ150にして計算してみました。すると、

格子数200×175

粗さはなくなっていると思います。

しかし、動画にして等速にするとスムーズに見えますがこれ実際にはカクカクです。とてもじゃないですが、リアルタイムでは難しそうです。ん~ここは改善の余地がありそうです。

番外編:苦労した点

今回の作業で苦労した点としてはテクスチャを貼り付ける作業です。

はじめはテクスチャの色を直接変えようとしていたのですが、どうやら2Dだとうまく行かないみたいです。

こちらのサイトのように2Dオブジェクトにテクスチャを貼り付けてやろうと試みたのですが、マテリアル自体の色は変えられるのですが、テクスチャの色が変わってくれませんでした。

原因はよくわかりません😫。当然3Dだとうまくできました。

また、シェーダーと呼ばれる描画方法を記述したプログラムを別に作る方法も考えました。

流体計算からシェーダーに値を送ってシェーダーで描画の表現を変えるという方法です。こちらなどを参考にしました。

これはまずシェーダーを理解するのが難しいというのと、一定の色に変化させるのはできたのですが、ピクセルごとに変化させるというのはわからず断念しました。

本屋にも何件か行ったんですが、今回のような作業はニッチなのかなかなか打開策が見つかられなかったです。

そしてもう諦めようとしていたときに今回の方法を見つけました。本当に良かったです。

まとめ

今回はUnity2Dで流体計算を自分で行ってそれを描画するということをやってみました。まとめを以下に示します。

  • 流体挙動はナビエ・ストークス方程式を計算することで再現可能
  • 格子ボルツマン法は比較的簡単に記述可能
  • 流体計算結果を使ってテクスチャを作成しRaw imageに貼り付けることで結果を描画可能

流体計算とその結果の描画はできたもののまだまだ改善の余地はありそうですので、今後もっと勉強して実際にゲームに使えるように改善していきたいと思います。

参考サイト,文献

コメント

タイトルとURLをコピーしました