テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

【Unity】C# Job Systemからでもランダムを使いたい

今回はC# Job Systemでランダムを使うアプローチについてです。

UnityEngine.Randomがメインスレッドでしか動作しない

シューティングの弾や移動の判断、様々な要因でランダムを使いたくなります。特に C# Job Systemでデモ的な何かを作ろうと思った時など、要素が同じ動きにならないように動きをバラけさせたくなります。
ここで UnityEngine.Randomがメインスレッドでしか動作しない という問題にぶち当たります。

UnityException : RandomRangeInt can only be called from the main thread

強引なアプローチではランダムテーブルを作ってズラすという物もありますが、今回は異なるアプローチを試します。

Unity.Mathematics.Random

Mathematicsに追加された新しいAPI Unity.Mathematics.Random を試します。
このAPIUnityEngine.Randomと異なり、以下のような特徴があります。

  • 複数のインスタンスを持てる
    (他の箇所でRandomを実行しても再現性がある)
  • 別スレッドからも呼べる
  • Burstで最適化される

特に有り難いのがインスタンスを持てる事による再現性ですが、これは逆を言えば インスタンスを用意し初期化しないと使えません 。static関数ではないので、インスタンスの管理や生成といった手間が入ります。

RandomをC# Job Systemで使ってみる

Randomを使用してみます。
作ったのは下のような物です。

  • ボールが跳ねる
  • 着地時に別の座標(ランダム)へ移動

f:id:tsubaki_t1:20181029230516g:plain

とりあえずジョブにランダムを突っ込む。しかし

ランダムをとりあえず突っ込んでみます。普通に C# Job Systemのフィールドとして登録 し、中で使用するという感じです。
この時、UnityEngine.RandomUnity.Mathematics.Randomの宣言が重複するので、using Random = Unity.Mathematics.Random;とか宣言しておきます。

f:id:tsubaki_t1:20181029231444j:plain f:id:tsubaki_t1:20181029231127j:plain

これで実行してみますが、Random自体は使えてるのですが 値が非常に偏ります 。 対策にと毎フレームSeedを設定しても下のような感じ。対策しないと本当に偏る…というか最早固定値?

f:id:tsubaki_t1:20181029231851g:plain

同じ結果が出ないようにする

というのもジョブは実行時にコピーを作るので、Nextで次の値を取得しても大本に反映されない ため、全てのジョブで 最初のRandom を取得してしまってるからだと思われます。実際、上のはジョブ生成時に新しいSeedを与えた場合で、Seedを与えなければ全てのジョブが毎回同じ結果を返します。

毎回同じ結果を返さない為にジョブ毎にSeedを変えるかインスタンスを共有するかする必要があり、スレッドセーフにしてアクセスとか色々考えましたが、最終的に NativeArrayでインスタンスを共有してシングルスレッドでBurstかけてぶん回したほうが早いなー という結論に至りました。Burst強い。並列処理だと複数のスレッドからRandomにアクセスしちゃうのでヤバイですが、まぁIJobProcessComponentData.ScheduleSingleでシングルスレッドで動かせばまあ良いかなという発想です。

あ、別にStateを共有しても問題ないです。進行を保存出来れば良いので。

f:id:tsubaki_t1:20181029232825j:plain

コード

gist.github.com

感想

Randomを毎回維持してくれるのは有り難い事なのですが、インスタンスが独立してるせいで若干面倒くさい目に合いました。

なお .NET 4系を要求 します。.NET 3系の場合は諦めてランダムテーブルなり自前実装なりをするのが良いです。

関連

Randomのソースコード。xorshiftベース github.com

”ランダム”についての詳しい解説

www.slideshare.net

乱数の独自実装が紹介されています。 kan-kikuchi.hatenablog.com