Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using Unity.Collections;
- using Unity.Entities;
- using Unity.Jobs;
- using Unity.Mathematics;
- using Unity.Transforms;
- using Unity.Transforms2D;
- internal sealed class FlowCollisionSystem : JobComponentSystem
- {
- private const int
- WallWeight = 1,
- TilesPerUnit = 8,
- WallThickness = 50,
- BoundsUnitSize = 30,
- BoundsTileSize = BoundsUnitSize * TilesPerUnit;
- private const float
- Speed = 0.1f,
- GravityScale = 0f,
- ParticleUnitSize = 1f,
- HalfParticleUnitSize = ParticleUnitSize * 0.5f,
- HalfParticleTileSize = HalfParticleUnitSize * TilesPerUnit;
- [Inject]
- private ParticleGroup particleGroup;
- private NativeArray<int> integerField;
- private NativeArray<float2> vectorField;
- protected override JobHandle OnUpdate(JobHandle inputDeps)
- {
- const int TileCount = BoundsTileSize * BoundsTileSize;
- this.TryDisposeNativeArrays();
- this.integerField = new NativeArray<int>(
- TileCount,
- Allocator.TempJob,
- NativeArrayOptions.ClearMemory);
- this.BuildWalls();
- var integerJob = new BuildIntegerFieldJob()
- {
- IntegerField = this.integerField,
- Positions = this.particleGroup.Positions,
- }.Schedule(this.particleGroup.Length, 1, inputDeps);
- this.vectorField = new NativeArray<float2>(
- TileCount,
- Allocator.TempJob,
- NativeArrayOptions.UninitializedMemory);
- var vectorJob = new BuildVectorFieldJob()
- {
- IntegerField = this.integerField,
- VectorField = this.vectorField,
- }.Schedule(TileCount, 64, integerJob);
- var navigateJob = new NavigateJob()
- {
- Headings = this.particleGroup.Headings,
- Positions = this.particleGroup.Positions,
- Speeds = this.particleGroup.Speeds,
- VectorField = this.vectorField,
- }.Schedule(this.particleGroup.Length, 1, vectorJob);
- return navigateJob;
- }
- protected override void OnDestroyManager()
- {
- this.TryDisposeNativeArrays();
- }
- private void BuildWalls()
- {
- for (int x = 0; x < BoundsTileSize; x++)
- {
- for (int i = 0; i < WallThickness; i++)
- {
- int leftIndex = x + (i * BoundsTileSize);
- int rightIndex = x + ((BoundsTileSize - (1 + i)) * BoundsTileSize);
- this.integerField[leftIndex] = (WallThickness - i) * WallWeight;
- this.integerField[rightIndex] = (WallThickness - i) * WallWeight;
- }
- }
- for (int y = 1; y < BoundsTileSize - 1; y++)
- {
- for (int i = 0; i < WallThickness; i++)
- {
- int bottomIndex = i + (y * BoundsTileSize);
- int topIndex = (BoundsTileSize - (1 + i)) + (y * BoundsTileSize);
- this.integerField[bottomIndex] = (WallThickness - i) * WallWeight;
- this.integerField[topIndex] = (WallThickness - i) * WallWeight;
- }
- }
- }
- private void TryDisposeNativeArrays()
- {
- if (this.integerField.IsCreated)
- {
- this.integerField.Dispose();
- }
- if (this.vectorField.IsCreated)
- {
- this.vectorField.Dispose();
- }
- }
- [ComputeJobOptimization]
- private struct BuildIntegerFieldJob : IJobParallelFor
- {
- [NativeDisableParallelForRestriction]
- public NativeArray<int> IntegerField;
- [ReadOnly] public ComponentDataArray<Position2D> Positions;
- public void Execute(int particleIndex)
- {
- this.IncrementOccupiedTiles(particleIndex);
- }
- private void IncrementOccupiedTiles(int index)
- {
- var position = this.Positions[index];
- var offsetPosition = position.Value + (BoundsUnitSize * 0.5f);
- int
- minX = (int)((offsetPosition.x - HalfParticleUnitSize) * TilesPerUnit),
- maxX = (int)((offsetPosition.x + HalfParticleUnitSize) * TilesPerUnit),
- minY = (int)((offsetPosition.y - HalfParticleUnitSize) * TilesPerUnit),
- maxY = (int)((offsetPosition.y + HalfParticleUnitSize) * TilesPerUnit);
- for (int y = minY; y < maxY; y++)
- {
- for (int x = minX; x < maxX; x++)
- {
- this.IntegerField[x + (y * BoundsTileSize)] += 1;
- }
- }
- }
- }
- [ComputeJobOptimization]
- private struct BuildVectorFieldJob : IJobParallelFor
- {
- [NativeDisableParallelForRestriction]
- [ReadOnly] public NativeArray<int> IntegerField;
- [NativeDisableParallelForRestriction]
- public NativeArray<float2> VectorField;
- public void Execute(int index)
- {
- this.VectorField[index] = this.CalculateVector(index);
- }
- private float2 CalculateVector(int index)
- {
- float2 vector = 0;
- int tileX = index % BoundsTileSize;
- int startX = tileX > 0 ? tileX - 1 : tileX;
- int endX = tileX < (BoundsTileSize - 1) ? tileX + 1 : tileX;
- int tileY = index / BoundsTileSize;
- int startY = tileY > 0 ? tileY - 1 : tileY;
- int endY = tileY < (BoundsTileSize - 1) ? tileY + 1 : tileY;
- for (int y = startY, vy = 1; y <= endY; y++, vy--)
- {
- for (int x = startX, vx = 1; x <= endX; x++, vx--)
- {
- int loopIndex = x + (y * BoundsTileSize);
- if (loopIndex == index)
- {
- continue;
- }
- var direction = math.normalize(new float2(vx, vy));
- vector += direction * this.IntegerField[loopIndex];
- }
- }
- return vector;
- }
- }
- [ComputeJobOptimization]
- private struct NavigateJob : IJobParallelFor
- {
- [NativeDisableParallelForRestriction]
- [ReadOnly] public NativeArray<float2> VectorField;
- [ReadOnly] public ComponentDataArray<Position2D> Positions;
- public ComponentDataArray<Heading2D> Headings;
- public ComponentDataArray<MoveSpeed> Speeds;
- public void Execute(int particleIndex)
- {
- float2 vector = this.CalculateVector(particleIndex);
- ApplySpeedMultiplier(ref vector);
- ApplyGravity(ref vector);
- this.Headings[particleIndex] = new Heading2D() { Value = math.normalize(vector) };
- this.Speeds[particleIndex] = new MoveSpeed() { speed = math.length(vector) };
- }
- private float2 CalculateVector(int index)
- {
- float2 vector = 0;
- var position = this.Positions[index];
- var offsetPosition = position.Value + (BoundsUnitSize * 0.5f);
- int
- minX = (int)((offsetPosition.x - HalfParticleUnitSize) * TilesPerUnit),
- maxX = (int)((offsetPosition.x + HalfParticleUnitSize) * TilesPerUnit),
- minY = (int)((offsetPosition.y - HalfParticleUnitSize) * TilesPerUnit),
- maxY = (int)((offsetPosition.y + HalfParticleUnitSize) * TilesPerUnit);
- for (int y = minY; y <= maxY; y++)
- {
- for (int x = minX; x <= maxX; x++)
- {
- vector += this.VectorField[x + (y * BoundsTileSize)];
- }
- }
- return vector;
- }
- private static void ApplySpeedMultiplier(ref float2 vector)
- {
- vector *= Speed;
- }
- private static void ApplyGravity(ref float2 vector)
- {
- vector += new float2(0f, -9.82f) * GravityScale;
- }
- }
- private struct ParticleGroup
- {
- public ComponentDataArray<Heading2D> Headings;
- public ComponentDataArray<Position2D> Positions;
- public ComponentDataArray<MoveSpeed> Speeds;
- public int Length;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement