ここではUnityでランダムな値(乱数)を作る方法について説明します。
※この記事で使用しているUnityのバージョン:Unity2019.1
乱数とは?
乱数は文字通りランダムな値のことです。ゲームにおいて乱数はとても重要で、例えば次のようなギミックを実現するのに役立ちます。
- 何が入っているか分からない宝箱
- 話しかけるごとにランダムなセリフをしゃべるNPC
- ランダムな技を繰り出してくる敵キャラ
このように乱数はゲーム制作で欠かせない要素なので、これから紹介する乱数の作り方くらいは押さえておいたほうが良いでしょう。
いろいろな乱数の作り方
それではさっそく乱数の作り方を紹介していきます。
Random.Rangeメソッドを使った乱数の作り方
まず、Unityで最も一般的な乱数の作り方がRandom.Rangeメソッドを使う方法です。このメソッドは第一引数と第二引数に指定した範囲内でランダムな値を生成します。使い方はとても簡単で、例えば
float min = 0f; float max = 1.5f; float random = Random.Range(min, max);
と書けば変数randomには0~1.5までのランダムな値が代入されます。
なお引数には整数型(int)も使えますが、その場合は第二引数の値は生成される乱数の範囲に含まれないことに注意してください。つまり、例えばRandom.Range(0,3)なら0~2までの整数が返ってくるというわけです。
偏りのある乱数の作り方
さて、ゲームを作っていると、一様な乱数だけでなく偏りのある乱数を作りたくなる場合もあります。そのような場合はアニメーションカーブを使うと簡単に偏りのある乱数を作ることができます。
アニメーションカーブを渡すとそれに沿った「偏りのある乱数」を返すメソッドは次のように書くことができます。
public static float CurveWeightedRandom(AnimationCurve curve) { return curve.Evaluate(Random.value); }
これは別の言い方をすると、「アニメーションカーブの横軸の値をランダムに選び、それに対応する縦軸の値を返す」メソッドです。
このメソッドでは、例えば次のようなアニメーションカーブを渡した場合は偏りが生じません。
しかし次のようなアニメーションカーブを渡すと「真ん中の値が出やすく」なります。
つまり、カーブの勾配が緩やかな部分の値が出やすく・勾配が急な部分の値が出にくくなるというわけです。
ランダムな座標の作り方
最後に、ゲームではランダムな座標にゲームオブジェクトを出現させたい、という場合がよくあります。そのようなときに役立つランダムな座標の生成方法を4通り紹介しますね。
- 立方体の中のランダムな座標を得る方法
- 球体の中のランダムな座標を得る方法
- 球体表面のランダムな座標を得る方法
- 2次元の円の内側のランダムな座標を得る方法
立方体の中のランダムな座標を得る方法
1つ目は立方体の中のランダムな座標を得る方法です。これはとても簡単で、例えば一辺が1mの立方体の中のランダムな座標を返すメソッドは次のように書くことができます。
public static Vector3 RandomVec() { return new Vector3(Random.value, Random.value, Random.value); }
実行結果を確認してみると次の画像のようになりました(分かりやすいようにボックスコライダーを表示しています)。
球体の中のランダムな座標を得る方法
2つ目は球体の中のランダムな座標を得る方法です。これはRandom.insideUnitSphereを使うことで簡単に書くことができます。
public static Vector3 RandWithinRadius(float radius) { return Random.insideUnitSphere * radius; }
実行例は次の通りです。
球体表面のランダムな座標を得る方法
お次は球体の表面上のランダムな座標を得る方法です。こちらはRandom.onUnitSphereを使うと簡単に書けます。
public static Vector3 RandOnSphereSurface(float radius) { return Random.onUnitSphere * radius; }
確認してみると、確かに球の表面上の座標が得られることが分かります。
2次元の円の内側のランダムな座標を得る方法
最後は2次元の円の内側のランダムな座標を得る方法です。これについてはRandom.insideUnitCircleというのがあるので、それを使えばOKです。
public static Vector3 RandWithinCircle(float radius) { return Random.insideUnitCircle * radius; }
確認してみると次の画像のようになりました。