[Unity]PerlinNoiseでランダムなマップを生成しよう

Unity
UnsplashMo Baghdadiが撮影した写真のMo Baghdadiが撮影したイラスト素材

まずはマップ生成!

どうも、次回作のゲーム開発を行っている壁です

まずはじめの作業としてマップを生成したいと思っているのですが

自動でマップを生成してくれるといいですよね

そういったものはないか調べたところ

Mathf.PerlinNoise

というものがヒットしました

こちらを使ってマップ生成を実現していこうと思います!

パーリンノイズ (Perlin Noise)とは?

パーリンノイズとは連続的なランダムな数値を返すものだそうです

具体的にどうなるか5×5の配列に実際の値を出力したのが以下です

0.34  0.43  0.39  0.28  0.24  
0.28  0.38  0.34  0.23  0.19  
0.34  0.43  0.39  0.28  0.24  
0.43  0.53  0.49  0.38  0.34  
0.47  0.56  0.52  0.41  0.37  

確かに一番最初は0.34で次が0.43となっていて

急に0.19とかになっていないので隣との差で考えると

なだらかに数値が増減しているって感じですね

こういったランダム数値を返してくれるのがパーリンノイズなんだそうです

これを使うことによって例えば数値が0.30未満の場合は水

0.30以上であれば陸ってすれば水と陸が自然な形で自動生成できるってわけです

実際にこちらの条件でタイルマップを敷き詰めたのが以下です

こんな感じでマップ生成できるので便利ですね

マイクラとかもこういったアルゴリズムでマップを自動生成しているそうです!

Unityでのパーリンノイズの使い方

公式の説明は以下を参照ください!

Mathf-PerlinNoise – Unity スクリプトリファレンス
2D のパーリンノイズを生成します

以下の通り

Mathf.PerlinNoise(x, y)

の関数を使うと前述のようなランダム値が出てきます。

ここでx,yはfloat型です。

またx,yは公式の説明によると

サンプル点のx座標とy座標とのことです

これだけ見ると座標?意味わからんって

私は思いました

ここについてはパーリンノイズをもうちょっと知ると

そーいうことかって思いますので

以下でパーリンノイズについてもう少し詳しく説明します

パーリンノイズは決定論的ノイズ

まずパーリンノイズは決定論的ノイズらしいです

で、決定論的ノイズとはなにかというと

毎回同じ座標を入力すると毎回同じ値を返す

ということだそうです

だから座標ってどういうことだよって

思うかと思いますが

ここはAIに聞いたところ以下でよくわかりました

パーリンノイズはサイン波の複雑版

例えば高校の数学で出てきたサイン、コサイン、タンジェントの

サインはy = sin(x)という式で一般化されていますが

xに色々な角度を入力するとyが算出されますね

例えばsin(0) = 0ですし
sin(π/2) = 1です

サインは半径1の円の円周上のどこの座標かを

x(角度)を入力することでyがわかるような感じです

これを半径1の円ではなくものすごく複雑な平面にしたものが

パーリンノイズなんだなーって私は理解しました

これでx,yを入力すると値が出てきて

更にx,yが近いほど値に差がなくなるっていうのが

なんとなく理解できればと思っています

x,y座標の決め方について

最後に引数として渡すx座標、y座標の決め方ですね

こちらは公式のコードでは以下のようになっていました

float xCoord = xOrg + x / noiseTex.width * scale;
float yCoord = yOrg + y / noiseTex.height * scale;
float sample = Mathf.PerlinNoise(xCoord, yCoord);

PerlinNoise関数にはxCoord、yCoordを引数として渡しています

で、どちらも同じような計算式で行っているのでxの方だけ

解説しようと思います

まずxOrgというのがあります

こちらはそもそも座標をずらすという意味があるようです

前述した通り同じ値を引数で渡すと同じ値が返ってくるので

そもそもの座標をごっそりずらす、という意味でこちらのxOrgがあります

これをランダムの値にすることでマップ生成の座標が

全然変わってくるので全く違ったマップが出来上がるということになるわけです

次にx / noiseTex.widthの部分です

こちらのnoiseTex.widthはいわばマップの横幅ですね

それに対して生成したいマップの現在地座標をxとしていて

x / noiseTex.widthとすることで0~1の範囲の値が取得できますね

0~1の範囲でちょっとずつ値をずらしていくことで

パーリンノイズの値自体も連続的に変わっていくようになるということです

最後にscaleを掛けていることで

scaleの値によってパーリンノイズの値の差が

なだらかに変わっていくか急に変わっていくのかが

変わりますね

なのでscaleの値が大きければ大きいほど急な変化になり

細かい島がぶつぶつあるようなマップが生成されるということになるようです

おわり!

ということで

自分用ではありますがパーリンノイズ関数について

解説いたしました!

UnsplashErnests Vagaが撮影した写真のErnests Vagaが撮影したイラスト素材
タイトルとURLをコピーしました