ECS:随机数

各个工作线程的随机数种子是稳定的,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);
       randomArray[nativeThreadIndex] = rand;
// ... } } }

 

posted @ 2020-06-10 21:37  斯芬克斯  阅读(868)  评论(2编辑  收藏  举报