OpenAssetOrgのアセットで2Dゲームを作る(17) ランダムだけど毎回同じ
「敵が一直線ではおかしいので、適度に散らばってくれるように調整中」
妹「王様が多すぎなのでは? 王とはいったい……」
「毎フレーム1人出てくるようにしたらこうなってしまった」
妹「あとまた卑怯な王様いるよ。壁の中移動してるし」
「これは乱数の範囲をミスってるね。壁の分を計算してなかった」
「もう少しまともになるように調整した。適切な敵の分量は、敵の速さとか弾の強さにもよるから、例えば貫通弾ならさっきの量でもわりと戦えそうな気がする。なのでいくつか変数で調節可能にして、おおまかな仕組みを作った」
妹「敵はレベル上に配置しないの?」
「そういうやり方でもいいんだけど、どうしても時間がかかる。それに画面外に居る時の無敵判定とか色々めんどくさい問題も起きそうだったから、ブループリントからランダムでスポーンするやり方にした。ただ毎回同じように出てきて欲しいから、~FromStreamと付いてる系のRandomノードを使っている」
妹「それってどういう仕組みなの?」
「乱数をどうやって作るかっていうと、基本的には計算でやってる。最初の数字(Seed値)が同じで、それに対して同じ順番で同じ計算をすると、同じ結果になるのが乱数の原理。シミュレーションゲームで何回リセットしても同じ結果になるというのもこの理屈」
妹「でも普通のRandomだと毎回数字違うんだよね? ゲームでもリセットするたびに変わるやつあるし。あれは計算してないの?」
「計算してるんだけど、計算式の中にその時の時計の秒数とか、フレーム数とか、毎回数字が変わるようなのを混ぜてるんだよ。こうすれば人間から見たら不規則な変化に見える。毎回違うのとデバッグの時に困るし、最悪クリア不能になることもありえる」
妹「でも毎回一緒だとつまらないのでは?」
「そのへんはゲームによるけど、毎回変えたい場合はSeed値に時計の数字を使って、その後はFromStreamで固定っていう手もある。完全ランダムと違うのは、その最初のSeed値をどこかに記録したり、画面上に表示しておけば、後で再現が出来るから」
妹「完全ランダムだと再現できないの?」
「乱数の結果を全部保存しないといけないから、数百回とか数千回とかになってくるでしょ。その結果を読み込めるようにブループリントも色々書き換えないといけない。理屈では出来るけど……」
妹「絶対やりたくないかんじが漂っている」
「いつどこでバグるかわからないし、完全ランダムにするのはエフェクトみたいなのだけでいいと思う。あとTickの中で乱数を使う場合は、フレームレートも固定じゃないと、乱数は一緒でもタイミングが変わるから、完全に同じにはならない場合がある」