PONOS Advent Calendar 2021の16日目の記事です。
昨日は@714hoさんの「Unityログにタグをつけて見やすくする方法」でした!
#はじめに
※間違いや不自然な日本語があったらスミマセン。
次の記事を参考にしたものです(英語):https://blog.redbluegames.com/generating-predictable-random-numbers-in-unity-c97b7c4895ec
UnityEngine.Randomを使うか?System.Randomを使うか?は考えたことないですか?
予測できるランダム値を生成したい場合は、UnityEngine.Randomは使いにくいです。
UnityEngine.Randomはstaticであり、共通で使われるものなので、他のプラグインやコードに呼ばれる、又は初期化される可能性があります。
以下のように設定すれば、自分で制御できます:
public static class RandomUtils
{
public static System.Random RNGSingleton = new System.Random();
}
たとえば、確率で何かを行われる場合は以下のメソッドが使えます:
public static bool RandomChance(System.Random rng, int percent)
{
return rng.Next(0, 100) < percent;
}
もう一つの例です。こちらはレンジの中でランダムな値を返します:
public static bool RandomRange(System.Random rng, int min, int maxExclusive)
{
return rng.Next(min, maxExclusive);
}
普段はRNGSingletonをパラメータとしてパスします。
#予測できる値を生成する
たとえば、宇宙の中で遊べるゲームを作っています。
「銀河」をいくつか生成して、それぞれはさまざまな「惑星」を生成します。
この場合はまずシードを設定して、次にランダムを初期化します:
// シードを設定
int seed = RandomUtils.RandomRange(RandomUtils.RNGSingleton, 0, int.MaxValue);
// ランダムを初期化
var random = new System.Random(seed);
// それぞれの銀河が同じランダムにより生成
foreach(var galaxy in galaxies)
{
galaxy.Generate(random);
}
「銀河」はまた「惑星」に「random」をパスするイメージです。
例:
// galaxy = 銀河
public class Galaxy
{
// 生成メソッド
public void Generate(System.Random random)
{
// 50%の確率で…
if (RandomUtils.RandomChance(random, 50))
{
// 大きな惑星を追加
var planet = new BigPlanet();
planet.Generate(random);
}
else
{
// 小さな惑星を追加
var planet = new SmallPlanet();
planet.Generate(random);
}
}
}
こうやって、シードを保存すれば毎回同じ宇宙を生成できます。
明日は@nisei275さんです!