Example #1
0
    protected override void OnUpdate()
    {
        if (spawned)
        {
            return;
        }
        spawned = true;

        // Instead of performing structural changes directly, a Job can add a command to an EntityCommandBuffer to
        // perform such changes on the main thread after the Job has finished. Command buffers allow you to perform
        // any, potentially costly, calculations on a worker thread, while queuing up the actual insertions and
        // deletions for later.
        var commandBuffer = m_EntityCommandBufferSystem.CreateCommandBuffer().AsParallelWriter();


        var poissonsManaged = FastPoissonDiskSampling.Sampling(Vector2.zero, Area, Constants.MinDistanceBetweenAgents).ToArray();
        var poissons        = new NativeArray <Vector2>(poissonsManaged, Allocator.TempJob);



        // Schedule the job that will add Instantiate commands to the EntityCommandBuffer.
        // Since this job only runs on the first frame, we want to ensure Burst compiles it before running to get the best performance (3rd parameter of WithBurst)
        // The actual job will be cached once it is compiled (it will only get Burst compiled once).
        var spawnerJob = Entities
                         .WithName("SpawnerSystem")
                         .WithBurst(FloatMode.Default, FloatPrecision.Standard, true)
                         .ForEach((Entity entity, int entityInQueryIndex, ref Spawner spawner, in LocalToWorld location) =>
        {
            var random   = new Random(1);
            spawner.Area = Vector2.one * Constants.AreaSize * Constants.MinDistanceBetweenAgents;

            //Debug.Log($"Spawning with infection ratio of {spawner.InitialInfectedRatio}");

            //for (var x = 0; x < spawner.CountX; x++)
            {
                //for (var y = 0; y < spawner.CountY; y++)
                for (var i = 0; i < poissons.Length; i++)
                {
                    var poisson  = poissons[i];
                    var instance = commandBuffer.Instantiate(entityInQueryIndex, spawner.Prefab);

                    // Place the instantiated in a grid with some noise
                    const float dist = 1.7f;
                    //var position = math.transform(location.Value, new float3(x * dist, noise.cnoise(new float2(x, y) * 0.21F) * 2, y * dist));
                    var position = math.transform(location.Value, new float3(poisson.x, noise.cnoise(new float2(poisson.x, poisson.y) * 0.21F) * 2, poisson.y));


                    commandBuffer.SetComponent(entityInQueryIndex, instance, new Translation {
                        Value = position
                    });
                    commandBuffer.SetComponent(entityInQueryIndex, instance, new LifeTime {
                        Value = random.NextFloat(1.0F, 10.0F)
                    });
                    commandBuffer.SetComponent(entityInQueryIndex, instance, new RotationSpeed {
                        RadiansPerSecond = math.radians(random.NextFloat(25.0F, 90.0F))
                    });


                    AgentState state = AgentState.Healthy;
                    var rand         = random.NextFloat();
                    if (rand < spawner.InitialInfectedRatio)
                    {
                        state = AgentState.Infected;
                    }

                    // -2 because game stalls a second when it starts
                    var dt = random.NextFloat() * Constants.TickTime - Constants.TickDelayTime;

                    commandBuffer.SetComponent(entityInQueryIndex, instance, new Agent
                    {
                        State         = state,
                        DeltaTime     = dt,
                        IsWearingMask = spawner.WearingMask,
                    });;


                    if (state == AgentState.Healthy)
                    {
                        spawner.TotalHealthy++;
                    }
                    else
                    {
                        spawner.TotalInfected++;
                    }
                }
            }

            //commandBuffer.DestroyEntity(entityInQueryIndex, entity);
        }).ScheduleParallel(Dependency);

        Dependency = spawnerJob;
        var disposeJobHandle = poissons.Dispose(Dependency);

        Dependency = disposeJobHandle;

        // SpawnJob runs in parallel with no sync point until the barrier system executes.
        // When the barrier system executes we want to complete the SpawnJob and then play back the commands
        // (Creating the entities and placing them). We need to tell the barrier system which job it needs to
        // complete before it can play back the commands.
        m_EntityCommandBufferSystem.AddJobHandleForProducer(Dependency);
    }
Example #2
0
    public override void Generate(bool reallocate)
    {
        base.Generate(reallocate);
        BaseTerrain t = gameObject.GetComponentInParent <BaseTerrain>();

        if (!reallocate)
        {
            for (int i = 0; i < t.resolution; i++)
            {
                for (int j = 0; j < t.resolution; j++)
                {
                    elevationValues[i, j] = 0;
                    colorValues[i, j]     = Color.clear;
                }
            }
        }

        Random.InitState(seed);

        List <Vector2> craterPositions;

        if (poissonSampling)
        {
            craterPositions = FastPoissonDiskSampling.Sampling(Vector2.zero, Vector2.one * t.size, t.size / Mathf.Sqrt(craters));
        }
        else
        {
            craterPositions = new List <Vector2>((int)craters);
            for (int i = 0; i < craters; i++)
            {
                craterPositions.Add(new Vector2(Random.value, Random.value) * t.size);
            }
        }

        FastNoiseSIMD shapeNoise = new FastNoiseSIMD(seed);

        shapeNoise.SetNoiseType(FastNoiseSIMD.NoiseType.Perlin);
        float[] shapeNoiseSet = shapeNoise.GetNoiseSet(0, 0, 0, t.resolution, 1, t.resolution, t.size / t.resolution / shapeNoiseScale);

        float[] rcNoiseSet = ridgeColorNoise.fastNoiseSIMD.GetNoiseSet(0, 0, 0, t.resolution, 1, t.resolution, t.size / t.resolution);
        float[] hcNoiseSet = holeColorNoise.fastNoiseSIMD.GetNoiseSet(0, 0, 0, t.resolution, 1, t.resolution, t.size / t.resolution);

        foreach (Vector2 craterPos in craterPositions)
        {
            float variation = 0;
            if (enableVariation)
            {
                variation = Mathf.Pow(Random.Range(0f, 1f), Mathf.Exp(-variationShapeFactor / 5)) * 2 - 1;
            }

            float r  = Tools.Variate(radius, variation);
            float hd = Tools.Variate(holeDepth, variation);
            float hs = Tools.Variate(holeSteepness, variation);
            float rh = Tools.Variate(rimHeight, variation);
            float rs = Tools.Variate(rimSteepness, variation);
            float sf = Tools.Variate(smoothFactor, variation);

            float rcv    = Tools.Variate(ridgeColorValue, variation);
            float rca    = Tools.Variate(ridgeColorAlpha, variation);
            float rcspr  = Tools.Variate(ridgeColorSpread, variation);
            float rcdc   = Tools.Variate(ridgeColorDecay, variation);
            float rcnstr = Tools.Variate(ridgeColorNoiseStrength, variation);

            float hcv    = Tools.Variate(holeColorValue, variation);
            float hca    = Tools.Variate(holeColorAlpha, variation);
            float hcds   = Tools.Variate(holeColorDropSteepness, variation);
            float hcnstr = Tools.Variate(holeColorNoiseStrength, variation);

            float elevationRadius = r + Mathf.Sqrt(rh / rs);
            float colorRadius     = r + rcspr;
            float affectedRadius  = Mathf.Max(elevationRadius, colorRadius);
            int   minx            = Math.Max(0, Mathf.FloorToInt((craterPos.x - affectedRadius) / t.size * t.resolution));
            int   miny            = Math.Max(0, Mathf.FloorToInt((craterPos.y - affectedRadius) / t.size * t.resolution));
            int   maxx            = Math.Min(t.resolution, Mathf.CeilToInt((craterPos.x + affectedRadius) / t.size * t.resolution));
            int   maxy            = Math.Min(t.resolution, Mathf.CeilToInt((craterPos.y + affectedRadius) / t.size * t.resolution));

            MouseIndicator mi = gameObject.GetComponentInParent <BaseTerrain>().GetComponentInChildren <MouseIndicator>();

            for (int x = minx; x < maxx; x++)
            {
                for (int y = miny; y < maxy; y++)
                {
                    float dist = (new Vector2(x, y) / t.resolution * t.size - craterPos).magnitude + shapeNoiseSet[x + t.resolution * y] * shapeNoiseStrength;

                    // Adapted from S. Lague - https://github.com/SebLague/Solar-System
                    float hole = (Tools.Square(dist / r) - 1) * (hd + rh) * hs + rh;
                    float rimX = Mathf.Min(dist - elevationRadius, 0);
                    float rim  = rs * Tools.Square(rimX);

                    float craterShape = Tools.SmoothMax(hole, -hd, sf);
                    craterShape            = Tools.SmoothMin(craterShape, rim, sf);
                    elevationValues[x, y] += craterShape;

                    float distToRidge = Mathf.Abs(dist - r);
                    Color ridgeColor  = new Color(rcv, rcv, rcv, rca);
                    ridgeColor.a += rcNoiseSet[x + t.resolution * y] * rcnstr;
                    ridgeColor.a *= Mathf.Pow(Mathf.Max(0, 1 - distToRidge / rcspr), rcdc);

                    Color holeColor = new Color(hcv, hcv, hcv, hca);
                    holeColor.a += hcNoiseSet[x + t.resolution * y] * hcnstr;
                    holeColor.a *= Mathf.Max(0, Tools.SmoothMin(hcds * (1 - dist / r), 1, .5f));

                    colorValues[x, y] = Tools.OverlayColors(colorValues[x, y], holeColor);
                    colorValues[x, y] = Tools.OverlayColors(colorValues[x, y], ridgeColor);
                }
            }
        }
    }