UnityEngine.Random
は InitState(seed) を利用すると乱数を固定化できる
しかし一度使うと、次に Seed を利用しない乱数を利用したい場合戻す処理をする必要がある
そのため、通常の乱数と Seed を指定した乱数でよしなに利用できるようなクラスを作成しました
使い方
RandomUtility.Seed
指定した Seed を利用する
RandomUtility.Clear
Seed を利用しないようにする
RandomUtility.Reset
指定した Seed を初期化する
RandomUtility.Range
RandomUtility.Seed を実行していた場合は seed を利用した乱数
Seed を指定してなかったり Clear を実行していたら 通常の乱数
また、第3引数に Seed 値を指定していた場合 その Seed を利用して乱数を取得する
サンプル
private void Start() { var seed = 10; var index = 0; // Seed を指定 RandomUtility.Seed(seed); Debug.Log($"Print Range {++index} {RandomUtility.Range(0, 100)}"); Debug.Log($"Print Range {++index} {RandomUtility.Range(0, 100)}"); RandomUtility.Reset(seed); // リセットしたので1回目と同じになる Debug.Log($"Print Range {++index} {RandomUtility.Range(0, 100)}"); Debug.Log($"Print Range {++index} {RandomUtility.Range(0, 100)}"); // Seed を利用しないようにしたので、毎回ここは値が変わる RandomUtility.Clear(); Debug.Log($"Print Range {++index} {RandomUtility.Range(0, 100)}"); Debug.Log($"Print Range {++index} {RandomUtility.Range(0, 100)}"); RandomUtility.Reset(seed); // seed を指定しても実行できる Debug.Log($"Print Range {++index} {RandomUtility.Range(0, 100, seed)}"); Debug.Log($"Print Range {++index} {RandomUtility.Range(0, 100, seed)}"); }
通常乱数を使う 5,6 だけ異なった値が表示されています
コード
using System.Collections.Generic; /// <summary> /// 乱数を管理するクラス /// </summary> public static class RandomUtility { private static readonly Dictionary<int, UnityEngine.Random.State> _dic; private static UnityEngine.Random.State _defaultState; private static UnityEngine.Random.State _cacheState; private static int? _currentSeed; static RandomUtility() { _dic = new Dictionary<int, UnityEngine.Random.State>(); _defaultState = UnityEngine.Random.state; _currentSeed = null; } /// <summary> /// シードを使わないようにする /// </summary> public static void Clear() { _currentSeed = null; } /// <summary> /// シード値を変更する /// </summary> public static void Seed(int seed) { if (!_dic.ContainsKey(seed)) { UnityEngine.Random.InitState(seed); _dic.Add(seed, UnityEngine.Random.state); } _currentSeed = seed; } /// <summary> /// シードの順番を最初からにする /// </summary> public static void Reset(int seed) { if (!_dic.ContainsKey(seed)) return; UnityEngine.Random.InitState(seed); _dic[seed] = UnityEngine.Random.state; Seed(seed); } /// <summary> /// 乱数生成 /// シードが指定してあればシードを利用して生成する /// </summary> public static int Range(int min, int max, int? seed = null) { _cacheState = UnityEngine.Random.state; var r = 0; if (seed.HasValue) Seed(seed.Value); UnityEngine.Random.state = _currentSeed.HasValue ? _dic[_currentSeed.Value] : _defaultState; r = UnityEngine.Random.Range(min, max); if (_currentSeed.HasValue) _dic[_currentSeed.Value] = UnityEngine.Random.state; else _defaultState = UnityEngine.Random.state; UnityEngine.Random.state = _cacheState; return r; } }