Unityのランダム値生成における注意点


Unityのランダム値生成とは?

UnityではUnityEnginという名前空間の中にあるRandomクラスを標準で参照することができ、このクラス内の関数を使うことでランダム値を簡単に作成することができる。

■ランダム生成のサンプル

GenerateRandom.cs
//0f〜1.0fのランダム値を返してくれる
Debug.Log(UnityEngine.Random.value);

//指定した範囲のランダム値を返してくれる(サンプルは0f〜100f)
Debug.Log(UnityEngine.Random.Range(0f,100f));

【実行結果】
上がRandom.value, 下がRandom.Rangeの結果。

ランダム値の生成における注意点

Randomクラスの関数を使いランダム値の生成ができた!と思っても注意点がある。

■ランダム値は規則的

公式のサイトによると

「乱数生成は真にランダムでなく事前に決まった順番で番号を生成します」

つまり、このUnityEnginのランダム生成は、事前に決まった番号をあたかもランダム生成したように見せているだけなのだ。
どのようにしたら良いのだろうか。。

シード値の初期化

UnityEnginのランダム値はシード値によって決まる。

「乱数の値の選択は シード と呼ばれる値で選択されます。」

つまりシード値とは、ランダム値の元になる値のことを指す。
規則的なランダム値を擬似的に不規則にするには、このシード値を任意の値に指定(シード値の初期化)してあげることで可能となる。
逆を言うと、同じシード値を指定することで同じ結果を再現することもできる。

シード値の指定はInitState関数で行うことができる。
Random.InitState("シード値")

以下、シード値の指定と同じシード値により結果を再現するサンプル

GenerateRandom.cs
//シード値を10に指定
UnityEngine.Random.InitState(10);

//ランダム値の生成・出力
for(int i = 0; i < 5; i++)
{
    Debug.Log(UnityEngine.Random.value);
}

・一回目

・二回目

全く同じ結果を出力した。
つまり、ランダム値を生成する前に同じシード値を指定してあげれば何度でも同じ結果が取得でき、このシード値に毎回違う任意の値を指定してあれば毎回違うランダム値を生成することができる。

毎回違うシード値を指定

毎回違うシード値を指定するにはどのようにしたら良いのだろうか。
以下、一例のサンプル

GenerateRandom.cs
//現在時刻のミリ秒でシード値を初期化
UnityEngin.Random.InitState(DateTime.Now.Millisecond);
Debug.Log(UnityEngine.Random.value);

ランダム値を生成する前に現在時刻のミリ秒を指定してあげることで、そうそう同じシード値を指定することは無くなるため有効的である。

■int型とfloat型とで戻り値の型・有効範囲が違う

ランダム値の生成には、前述の通りRandom.valueとRandom.Rangeがあるが、Random.Rangeにおいては範囲に指定する引数の型により、戻り値の型や有効となる範囲が変わる。

戻り値の型の違い

Random.valueはfloat型の戻り値しか返さないのに対し、
Random.Rangeはfloat型とint型を指定することができ、指定する引数の型により戻り値の型が変わる。

GenerateRandom.cs
//float型で指定する
UnityEngin.Random.Range(0f,10.0f);//float型のランダム値を返す(例:0.7918238)
//int型で指定する
UnityEngin.Random.Range(0,10);//int型のランダム値を返す(例:2)

パターンによって使い分けを行えるため便利である。

引数型による指定範囲の違い

引数の型を変えることで、戻り値の型が変わるが、指定する有効範囲も変わってしまうため注意が必要だ。
以下、指定する有効範囲の違いを説明したサンプル

GenerateRandom.cs
//float型で指定する
UnityEngin.Random.Range(0f,10.0f);//0以上10以下までのflaot型の値を返す
//int型で指定する
UnityEngin.Random.Range(0,10);//0以上10未満のint型の値を返す

float型の場合、サンプルでは0〜10までの値を返すが、
int型では0以上10未満、つまり0〜9までの値を返すため気をつける必要がある。