各个工作线程的随机数种子是稳定的,RandomSystem的实现如下:
using Unity.Entities; using Unity.Jobs; using Unity.Burst; using Unity.Collections; using Unity.Jobs.LowLevel.Unsafe; using Random = Unity.Mathematics.Random; [UpdateInGroup( typeof(InitializationSystemGroup))] public class RandomSystem : ComponentSystem { public NativeArray<Random> randomArray; protected override void OnCreate() { base.OnCreate(); // JobsUtility.MaxJobThreadCount = 7 JobsUtility.MaxJobThreadCount = 128 randomArray = new NativeArray<Random>(JobsUtility.MaxJobThreadCount, Allocator.Persistent); var seed = new System.Random(); for (int i = 0; i < randomArray.Length; ++i) { randomArray[i] = new Random((uint)seed.Next()); } } protected override void OnDestroy() { randomArray.Dispose(); base.OnDestroy(); } protected override void OnUpdate() {} }
在其他的job中使用随机数,下面的代码去掉了冗余逻辑,只留下关键代码:
using UnityEngine; using Unity.Entities; using Unity.Transforms; using Unity.Jobs; using Unity.Burst; using Unity.Mathematics; using Unity.Collections; using Unity.Jobs.LowLevel.Unsafe; using Random = Unity.Mathematics.Random; public partial class TestSystem : JobComponentSystem { private EndSimulationEntityCommandBufferSystem endSimulationECBS; private EntityQueryDesc desc; protected override void OnCreate() { endSimulationECBS = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>(); desc = new EntityQueryDesc() { All = new ComponentType[] { ComponentType.ReadOnly<Translation>(), ComponentType.ReadOnly<Rotation>() }, }; base.OnCreate(); } protected override void OnDestroy() { base.OnDestroy(); } protected override JobHandle OnUpdate(JobHandle inputDeps) { EntityQuery query = GetEntityQuery(desc); NativeArray<Entity> generateSkillEntities = new NativeArray<Entity>(query.CalculateEntityCount(), Allocator.TempJob); TestJob job = new TestJob() { ecb = endSimulationECBS.CreateCommandBuffer().ToConcurrent(), randomArray = World.GetExistingSystem<RandomSystem>().randomArray, }; JobHandle handle = job.Schedule(this, inputDeps); endSimulationECBS.AddJobHandleForProducer(handle); return handle; } private struct TestJob : IJobForEachWithEntity<Translation, Rotation> { public EntityCommandBuffer.Concurrent ecb; // 属性标签很重要 [NativeDisableParallelForRestriction] public NativeArray<Random> randomArray; // JOB_ID [Unity.Collections.LowLevel.Unsafe.NativeSetThreadIndex] private int nativeThreadIndex; public void Execute(Entity entity, int index, [ReadOnly] ref Translation translation, [ReadOnly] ref Rotation rotation) { Random rand = randomArray[nativeThreadIndex]; float distance = rand.NextFloat(min, max); // ... } } }