【Unity】パーリンノイズ(PerlinNoise)って何ね? と思ったので遊んで試してみよう
Unityではパーリンノイズを使ってエフェクトのノイズをより自然に見せたり、Cinemachineで手振れを表現することができます。
「パーリンノイズを使えば自然な揺らぎを作れる」という認識はあったのですが、詳細について調べていなかったのでここで腰を据えて調べてみることにしました。
擬似乱数を使ってランダムな値を取得する場合との違いについても比較してみたいと思います。
パーリンノイズって何ね?
パーリンノイズ(Perlin Noise)とはコンピュータグラフィクスでよく使われるテクスチャ作成のための技法。Ken Perlin(ケン・パーリン)さんが開発したのでパーリンノイズだそうです。人名がついた技法ってワクワクしますね。藤井システムとか、シライキムヒフンとか。
さて、このパーリンノイズはテクスチャ作成のために使われるだけあって、滑らかに値が変化するノイズになっています。どういうことかというと、Randomクラスなどの擬似乱数では隣り合う値は急激に変化するような値になります。
例えば以下の画像は横軸にサンプル番号、縦軸にRandom.valueの値(0から1まで)をとったものです。ゲーム実行時にテクスチャを生成してRawImageのオブジェクトに流し込んでいます。この画像では隣り合うサンプル番号では値に関連性はなく、無秩序な散布図になっています。
一方、パーリンノイズを使って横軸にサンプル番号、縦軸にノイズの値(0から1まで)をとると以下のように隣り合う値と近い値になっています。完全に無秩序な値ではないので、例えば時間変化によって値が変動する場合でも急激に変化することはありません。
急激に変化する値を使うのは無作為に選ぶような処理では嬉しいのですが、テクスチャにすると不自然な画像になります。上の画像でもただの砂嵐みたいになっちゃってますからね。なのである程度ランダム性はもちつつ、でも自然な感じでノイズを発生させたい時に便利です。
パーリンノイズのテクスチャ
パーリンノイズを使う際は以下のように2次元のテクスチャを生成することが多いかもしれません。この画像では取得した値をグレースケールに変換して色を配置しています。
もう少しスケールを変えてみたものがこちら。先ほどより変化が大きくなっています。
Unityではこのように2次元のパーリンノイズを生成する方法が提供されていて、MathfクラスのPerlinNoiseメソッドを使います。このメソッドではX座標とY座標を指定することで、特定の座標の値を取得することができます。取得される値は0fから1fで、0よりちょっと小さくなったり1よりちょっと大きくなったりするので、厳密に使いたい場合はClampメソッドを使うと良いでしょう。Clampメソッドについては以下の記事で解説しています。
Photoshopを使っている人なら雲模様でよく見ますね。あれも(たしか)パーリンノイズを使っています。
パーリンノイズのサンプルコード
パーリンノイズを使ってテクスチャを作成してみます。1次元のデータと2次元のデータの両方を作ってみましょう。
1次元のデータ
例えば以下の画像のように横軸にサンプル数、縦軸に値をとるグラフのような画像を生成するコードを書いてみます。
このコードではボタンを押した時にパーリンノイズを使ってテクスチャを生成しています。ボタンを押した時に呼ばれるGeneratePerlinArray()のメソッドの中でパーリンノイズを使って値のリストを取得しています。その値のリストをGenerateTexture()のメソッドに渡してテクスチャを生成しています。このテクスチャはメモリ上に存在するものなので、ゲームを停止すると消えます。
パーリンノイズは2次元座標を指定して値を取得します。GeneratePerlinArray()の中では「float value = Mathf.PerlinNoise(xValue, yValue);」といった形でX座標とY座標を指定します。X座標の値はループカウンタのiを使って変動させ、Y座標の値は固定値にしており、これによりある線上の値を順番に取得していくようになっています。
また、座標の計算に使っている「xOrigin」と「yOrigin」はX座標の原点とY座標の原点をどこにするかのオフセットです。パーリンノイズでは同じ座標を指定すると同じ値が取得できるので、オフセットを変化させることで別のパターンを取得することができます。「scale」はどれだけ細かい単位で値を取得していくかのスケールで、スケールが小さいとより緩やかに変化するように値を取得し、大きいとよりはっきりと変化するように値を取得するようにしています。スケールはUnityさんちのサンプルコードでも使っていたのでここでも導入しています。
GenerateTexture()のメソッドでは生成したパーリンノイズの値リストを使ってテクスチャを作成しています。シーン内に作成したRawImageのオブジェクトのRect Transformを取得してテクスチャサイズを指定し、白でピクセルを塗っています。パーリンノイズの値に応じて黒色で塗っていくことで、上で紹介した画像のようにグラフっぽく描画されます。
2次元のデータ
よく見るパーリンノイズのテクスチャを作ってみましょう。
こちらはシンプルにStart()の中から呼び出すようにしてみました。パーリンノイズを表示するRawImageのRect Transformからサイズを取得し、それを元にテクスチャを作成しています。for文では珍しくfloatでループカウンタを指定していて、1次元の場合と同様にループカウンタにスケールをかけてパーリンノイズの座標を求めています。
パーリンノイズは0から1までの値を返すため、そのままColorに突っ込んで色を作成しています。RGB全てが同じ値になってる色はグレースケールになるので、白、灰色、黒の画像が出来上がります。ループが終わったらピクセルをセットして画面に表示しています。
座標の原点を帰るとテクスチャのパターンが変わるのも面白いポイントですね。
パーリンノイズの使用例
Unityの機能の中でもパーリンノイズを使っている部分がいくつもあります。
パーティクル(Shuriken)
Unityのパーティクルシステムの機能では、ここのパーティクルの運動にノイズを加えることができます。このノイズで使用しているのはCurl Noiseという技術で、内部的にパーリンノイズを複数組み合わせて流体のような動きを表現しています。
Visual Effect Graph
Visual Effect Graph(VFX Graph)でもパーリンノイズを使用することができます。ノードとして使う場合は3次元のパーリンノイズも使うことができます。(MathfのPerlinNoiseは2次元のもの)
使えるノイズはパーリンノイズだけではなく上のパーティクルシステム(Shuriken)で使用していたCurl Noiseもあるので、パフォーマンスと相談しつつ選択するといい感じです。
Cinemachine
Cinemachineでは手振れを表現するためにパーリンノイズを使います。ノイズの設定に関してはアセットファイルとして別で定義できるので、こちらで作成すると良いでしょう。
Cinemachineのノイズは位置で3軸、回転で3軸と合計6つの次元でノイズを生成することができます。現実世界で手振れを起こしている場合にもこの6つの次元で微小なブレを起こしているのでこれをシミュレーションする形になります。揺れである以上、隣り合う値は近い値になっていた方がいいので、パーリンノイズは都合が良いんです。
まとめ
Unityで使えるパーリンノイズについて紹介しました。完全にランダムな値を取得するためというよりは、波のように時間経過で変化する値を扱うのに向いています。
ここではエフェクト系との関連がメインでしたが、パーリンノイズを使ってフィールドの高低差を自動的に表現する方法もできそうですね。これもそのうちやってみましょうか。
という訳でパーリンノイズを使ってなだらかに変化する地形を作るサンプルを以下のページで紹介しています。
パーリンノイズ系の記事は以下のページでまとめています。
ゲーム開発の攻略チャートを作りました!
-
前の記事
【Unity】地味に使い所があるMathfのClampについて知る 2020.12.29
-
次の記事
【Unity】パーリンノイズを使って地形を作ろう!【ランタイム編】 2020.12.31
コメントを書く