波動方程式の解説
安原祐二氏:Unityの安原です。今回は微分と積分の使い方について、少しお話ししていきましょう。
前回、前々回の動画で微分、積分、それぞれお話ししましたけれども、あれだけではなかなかわかりにくいところもあるかと思います。また、慣れも必要ですので、この動画を見てもらえると、より深く理解できるんじゃないかなと思います。
じゃあまず微分からいってみましょう。こちらが、波動方程式と呼ばれるものです。波動方程式でネットを調べるとこういう式が出てくるんですね。ゲームやアプリケーションではわりとよくある話だったりもします。
よくわからない記号がたくさんあって、この右側の三角形はラプラシアンの記号なんですね。ちょっとややこしいところもあると思います。これは一次元、二次元、三次元を全部含んだ話をしているので、今回は一次元に限定してお話ししていきましょう。
はい、この式になります。ちょっとまだややこしいと思いますが、1つずつ見ていきましょう。まずこの6の反対になっているような、ぐるっと回っているもの(∂)。これは偏微分記号です。
微分の時、f(x)という関数があったと思います。このようにxが1つだけの場合は微分でいいのですが、当然、関数の中には変数を2つ持つものもあるんですね。プログラムでいうと引数が2つあるみたいな。偏微分はそういう時に使うものだと、とりあえずは理解していて大丈夫です。傾きについて論じていることは、微分も偏微分も同じものです。
この2乗の付き方がちょっと不思議ですよね。これはどういうことかというと、この部分はこういう書き方ができます。
微分は、「ここにどの軸でちょっと動かすか」で、ここに関数を書くという書き方になります。この2乗は、uという関数を1回微分したものを、もう1回微分しているということになります。なので、こういう記号の重なりになって、2乗の位置がこういうかたちになるわけです。
uが偏微分記号を使っているということは、複数の変数で成り立っているというわけです。偏微分の記号はtとxがあるので、ここはtとxの関数なんだろうなとわかります。この四角の部分はこういうふうに置き換えられるわけですね。
こちら側も同様にこうなりまして、sの2乗分の1を付けると、この式はこの式と同じということになります。sは定数なので、まぁずっと付いていくだけで、意味的にはそんなに気にしなくても大丈夫なわけです。
プログラムで波を表現するための考え方
プログラムに落とし込んでいきましょう。波があって、その波の高さを、ある点の高さで表しているとします。例えばここに注目してみたとしましょう。この点が次にどうなるかがわかれば、波の記述ができるわけです。
では、時間軸的に次の波をここにしましょうか。時間はこちら側に進んでいるとして、未来の波はここ。ここがわからない。このわからない波の高さをNにしましょう。これは注目しているところのポイントです。注目している波の高さをVにしましょう。
まずこの変化について話します。これ(N)からこれ(V)を引いて、移動した時間の分で割れば、意味としてはこの式と一致するわけです。数学的には厳密には違いますが、プログラムに落とし込む時にはそれでいいわけですね。
なのでNからVを引いて、動いた分の時間をΔt。これは短い時間ですね。これでこの部分は表せました。
次はここです。この関数がどのくらい変化したかを知りたいので、今度は過去、previousのPにしましょう。過去の波の高さと今の波の高さを比較して、これと同じように差を出して、その差(N−V)と差(V−P)を引いて時間で割ればいいわけです。
この差が出たので、これとこれを引いてこうすれば、ここの部分に相当するものがプログラムで書けるようになったということです。これはこうなります。
こちらをx軸としましょう。これとこれは右隣だからR、左隣だからLにしましょうか。このL、V、Rの関係を同じようにやればこちら側も作れます。同じようにすると、これがここに相当するということになります。つまりここがΔxなわけです。
というわけで、この情報をこの式に突っ込んでN=の式を作れば、次の波の高さがわかるということになります。これを全部入れて整理すると、このRもNもVもPも全部わかっている値なので、わかっている値からこのNの値、次の点がわかります。
というわけで、この計算を1個ずつやっていけば、すべての点の1つ先の未来がわかるので、それを繰り返していけば動く波がプログラム上で表現できるということになります。
この部分に関しては定数になるので、プログラムで書く時は適当な定数にしたほうが楽かもしれません。とりあえず1を置いて実験するのが早いかもしれないですね。
Unityでちょっと作ってみると、こんな感じの波。そんなに難しいプログラムじゃないのですけれども、1つ注意するところは、前の状態を保持していなきゃいけないので、バッファを1個とっておく必要があります。それがあればそんなに難しくない計算になります。
適当に作ったものですが、こんなふうに、ちょっとしたゲームで波を使った動きなんかを作ったらおもしろいかもしれません。
ある情報によると、こういう波や流体があるアプリケーションは、ダウンロード数が1割多いらしいです。ある情報というのは、僕の勘ですけど(笑)。
「クロソイド曲線」のプログラムを書く方法
次は積分についてお話ししていきましょう。積分は、こんな例を持ってきました。クロソイド曲線というのがあって、この右側に出ていますが、こうニョロニョロと巻く、こんな曲線です。ネット上で調べるとこんな式が書いてあります。
∫と書いてあるので、「ん? なんか難しそう」と思うのですが、これはそんなに難しくないんですね。
いきなりプログラムを書いてみましょう。Unityを起動しましょう。これは完全に開いた直後の状態です。GameObjectを作って、トレイルレンダラーをここに足しましょうか。それで、クロソイドの軌跡をトレイルで描いてみましょう。ピンク色ですが、実験なのでこのままいきましょう。
Clothoidというスクリプトを作って、ここに動きを書いていきましょう。最初はこんな感じですね。Updateだけでよいので、positionの変更を書きましょう。
このpositionをどう変更するかですが、先ほどのクロソイドのを+=にするんですね。+=にして、xはCosの、θの代わりに徐々に変化する値としてTimeを使ってみましょう。
Timeを2乗して2で割る、つまり0.5を掛ける。本当ならば、ここにΔ・θに相当するものを掛けなきゃいけないんですが、今回はあえてここを省略してみましょう。はい、Sinのほうでyができます。0.5fということで、実はこれでクロソイド曲線ができてしまうんですね。
やってみましょう。さぁ、実行。どうかな? うん。できていますね、ニョロニョロと。先ほど見たような巻き方をしているじゃないですか。まぁ、そんなに難しくない話かなと思います。たったこれだけだったんですね。積分ってプログラムで書くとけっこう簡単になるんですよね。
よりシンプルな記述でクロソイド曲線を描く方法
これだけの話なんですけれども、せっかくなのでもう少し深く話してみましょうか。ここにちょっと注目してみましょう、2分のθ2乗。これは、実はこういうふうに書けるんです。xを積分すると、2分のxの2乗で、θを入れると2分のθ2乗。
これを知っていると、プログラムをこういうふうに直せます。先ほどTimeを使ったのはあんまりだったので、Timeの代わりにtにしましょう。それで、tはdeltaTimeだけ増えていくことにしましょう。
そうすると、Timeのところは全部tに置き換えられるので、t掛けるtに直して、まずこれで実行してみましょう。まぁ、なにも変わらないわけですね。
ではここから変えていきましょう。t1という変数を新たに作っておいて、徐々に増やしていくのはt1のほうにして、tはそのt1の積分にします。+=でdeltaTimeを掛けて足していく。
すると、このt2乗掛ける0.5というのを、tに置き換えられるんですね。そうすると、よりシンプルなものになったわけです。結果は変わりません。こういうことを知っていると、勘が働くというか、よりシンプルな記述でクロソイド曲線を描けるようになるという話ですね。
というわけで、積分の例でした。今回は微分と積分を1つずつ、ネット上で見つかる式をどうプログラムに落とし込むかという練習をしてみました。ぜひみなさんも、式を見たら怖がらずに1つずつ分解して考えればそんなに難しくはないので、使えるようになったらいいんじゃないでしょうか。以上です。