Mathmatics.Random returns the same value

I am trying to use rand to return a position randomly on the board. Every time the counter reaches zero it spawns at the same location. Its as if random never grabs the next ‘random’ number. I’m doing something wrong, any ideas?

    [UpdateAfter(typeof(BrickLayoutSystem))]
    [DisableAutoCreation]
    public class PowerUpCreateSystem : JobComponentSystem
    {
        private const float PowerUpHorizontalOffset = 2f;

        private EntityCommandBufferSystem _entityCommandBufferSystem;
        private NativeArray<Entity> _powerUpEntities;
        private Random _random;

        public NativeArray<Entity> PowerUps { get => _powerUpEntities; set => _powerUpEntities = value; }

        protected override void OnCreate()
        {
            _entityCommandBufferSystem = World.GetExistingSystem<BeginSimulationEntityCommandBufferSystem>();
            _random = new Random((uint)DateTime.UtcNow.Ticks);
        }

        protected override void OnDestroy()
        {
            base.OnDestroy();

            _powerUpEntities.Dispose();
        }

        protected override JobHandle OnUpdate(JobHandle inputDeps)
        {
            var random = _random;
            var deltaTime = Time.DeltaTime;
            var buffer = _entityCommandBufferSystem.CreateCommandBuffer().ToConcurrent();
            var powerUps = PowerUps;

            var handle = Entities.ForEach((Entity entity, int entityInQueryIndex, ref PowerUpCreateData createData, in PowerUpBoardData boardData) => {
                createData.TimeSincePowerUpCreated -= deltaTime;

                if (createData.TimeSincePowerUpCreated <= 0) {
                    var powerUp = powerUps[random.NextInt(0, powerUps.Length)];

                    var x = boardData.boardSize.x * 0.5f - PowerUpHorizontalOffset;
                    var powerUpPosition = new float3(random.NextFloat(-x, x), random.NextFloat(0, createData.SpawnRange), 0f);
                    var powerUpInstance = buffer.Instantiate(entityInQueryIndex, powerUp);

                    buffer.SetComponent(entityInQueryIndex, powerUpInstance, new Translation() { Value = powerUpPosition });

                    var randomTime = random.NextFloat(createData.MinTime, createData.MaxTime);
                    createData.TimeSincePowerUpCreated = randomTime;
                    Debug.Log($"Pos: {powerUpPosition}");
                }
            }).Schedule(inputDeps);

            _entityCommandBufferSystem.AddJobHandleForProducer(handle);

            return handle;
        }
    }

You are forgetting it is a struct, unless you write back the internal state it’ll return the same result everytime.

The pattern I usually follow is this.

// state 0 is an error
var random = new Random((uint)UnityEngine.Random.Range(1, int.MaxValue));

this.Entities.ForEach((Entity entity, int entityInQueryIndex) =>
{
    // if you don't set the state different for each entity/chunk then it'll return the same value for every thread as it will have the same state.
    random.InitState((uint)(random.state + entityInQueryIndex));
})
.ScheduleParallel();
3 Likes

Ahhhh, that was it. Thanks @