Skip to content

Commit

Permalink
merged container and neighbours, removed rebuild job
Browse files Browse the repository at this point in the history
  • Loading branch information
KOTlK committed Jun 1, 2023
1 parent 046ad39 commit cf87945
Show file tree
Hide file tree
Showing 12 changed files with 73 additions and 155 deletions.
2 changes: 1 addition & 1 deletion Package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "com.kotlk.celllistsecs",
"version": "0.1.2",
"version": "0.1.3",
"displayName": "Cell Lists",
"description": "Simple cell lists implementation for dividing game world into pieces",
"unity": "2021.3",
Expand Down
7 changes: 5 additions & 2 deletions Runtime/Components/CellNeighbours.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
namespace CellListsECS.Runtime.Components
using System.Collections.Generic;

namespace CellListsECS.Runtime.Components
{
public struct CellNeighbours
{
public int[] All;
public int[] NeighboursEntities;
public List<int> ContainingTransforms;
}
}
9 changes: 0 additions & 9 deletions Runtime/Components/TransformContainer.cs

This file was deleted.

3 changes: 0 additions & 3 deletions Runtime/Components/TransformContainer.cs.meta

This file was deleted.

8 changes: 3 additions & 5 deletions Runtime/Systems/CellListsInitSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ public class CellListsInitSystem : IEcsRunSystem
private readonly EcsPoolInject<CreateCellLists> _commands = default;
private readonly EcsPoolInject<Cell> _cells = default;
private readonly EcsPoolInject<CellNeighbours> _neighbours = default;
private readonly EcsPoolInject<TransformContainer> _entitiesLists = default;

public void Run(IEcsSystems systems)
{
Expand Down Expand Up @@ -116,16 +115,15 @@ int[] GetClosestIndexesFor(int i)

ref var neighboursComponent = ref _neighbours.Value.Add(cells[i].Item2);

neighboursComponent.All = list;
neighboursComponent.NeighboursEntities = list;
}

foreach (var (cell, cellEntity) in cells)
{
ref var cellComponent = ref _cells.Value.Add(cellEntity);
cellComponent = cell;

ref var container = ref _entitiesLists.Value.Add(cellEntity);
container.All = new List<int>();
ref var neighbours = ref _neighbours.Value.Get(cellEntity);
neighbours.ContainingTransforms = new List<int>();
}

systems.GetWorld().DelEntity(entity);
Expand Down
119 changes: 33 additions & 86 deletions Runtime/Systems/CellListsRebuildSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,114 +2,61 @@
using CellListsECS.Runtime.Utils;
using Leopotam.EcsLite;
using Leopotam.EcsLite.Di;
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using Unity.Profiling;
using Transform = CellListsECS.Runtime.Components.Transform;

namespace CellListsECS.Runtime.Systems
{
//No Jobs 100000: 2.55ms overall build
//No Jobs 300000: 24ms overall build
//Jobs 100000: 5ms overall build
//Jobs 300000: 30ms overall build
//Creating arrays for jobs takes 10x more time than an actual job
public class CellListsRebuildSystem : IEcsRunSystem
{
private readonly EcsFilterInject<Inc<Cell, CellNeighbours, TransformContainer>> _cellsFilter = default;
private readonly EcsFilterInject<Inc<Cell, CellNeighbours>> _cellsFilter = default;
private readonly EcsPoolInject<Cell> _cells = default;
private readonly EcsPoolInject<Transform> _transforms = default;
private readonly EcsPoolInject<CellNeighbours> _neighbours = default;
private readonly EcsPoolInject<TransformContainer> _containers = default;


private static readonly ProfilerMarker Overall = new(nameof(Overall));
private static readonly ProfilerMarker Once = new(nameof(Once));

public void Run(IEcsSystems systems)
{
Overall.Begin();
foreach (var entity in _cellsFilter.Value)
{
Once.Begin();
ref var cell = ref _cells.Value.Get(entity);
ref var cellNeighbours = ref _neighbours.Value.Get(entity);
ref var transformContainer = ref _containers.Value.Get(entity);
var neighbours = new NativeArray<(Cell, int)>(cellNeighbours.All.Length, Allocator.TempJob);
var transforms = new NativeArray<(Transform, int)>(transformContainer.All.Count, Allocator.TempJob);
var removeCommands = new NativeQueue<int>(Allocator.TempJob);
var addCommands = new NativeQueue<(int, int)>(Allocator.TempJob);
ref var neighbours = ref _neighbours.Value.Get(entity);

for (var i = 0; i < cellNeighbours.All.Length; i++)
for(var i = 0; i < neighbours.ContainingTransforms.Count; i++)
{
var neighbourEntity = cellNeighbours.All[i];
ref var component = ref _cells.Value.Get(neighbourEntity);
neighbours[i] = (component, neighbourEntity);
}

for (var i = 0; i < transformContainer.All.Count; i++)
{
var transformEntity = transformContainer.All[i];
var transformEntity = neighbours.ContainingTransforms[i];
ref var transform = ref _transforms.Value.Get(transformEntity);
transforms[i] = (transform, transformEntity);
}
if (CollisionDetection.AABBContainsPoint(cell.Position, cell.AABB, transform.Position))
continue;

var job = new RebuildJob()
{
Cell = cell,
Neighbours = neighbours,
Transforms = transforms,
RemoveCommands = removeCommands.AsParallelWriter(),
AddCommands = addCommands.AsParallelWriter()
}.Schedule(transforms.Length, 32);

job.Complete();
neighbours.ContainingTransforms.Remove(transformEntity);

while (removeCommands.Count > 0)
{
var i = removeCommands.Dequeue();
transformContainer.All.Remove(i);
}

while (addCommands.Count > 0)
{
var (cellEntity, transformEntity) = addCommands.Dequeue();

ref var targetContainer = ref _containers.Value.Get(cellEntity);
targetContainer.All.Add(transformEntity);
}

neighbours.Dispose();
transforms.Dispose();
addCommands.Dispose();
removeCommands.Dispose();
}
}

[BurstCompile]
public struct RebuildJob : IJobParallelFor
{
[ReadOnly] public Cell Cell;
[ReadOnly] public NativeArray<(Cell, int)> Neighbours;
[ReadOnly] public NativeArray<(Transform, int)> Transforms;

/// <summary>
/// transformEntity
/// </summary>
public NativeQueue<int>.ParallelWriter RemoveCommands;

/// <summary>
/// cellEntity, transformEntity;
/// </summary>
public NativeQueue<(int, int)>.ParallelWriter AddCommands;

[BurstCompile]
public void Execute(int index)
{
var (transform, transformEntity) = Transforms[index];

if (CollisionDetection.AABBContainsPoint(Cell.Position, Cell.AABB, transform.Position))
return;

RemoveCommands.Enqueue(transformEntity);

foreach (var (neighbourCell, neighbourEntity) in Neighbours)
{
if (CollisionDetection.AABBContainsPoint(neighbourCell.Position, neighbourCell.AABB, transform.Position))
foreach (var neighbourEntity in neighbours.NeighboursEntities)
{
AddCommands.Enqueue((neighbourEntity, transformEntity));
break;
ref var neighbourCell = ref _cells.Value.Get(neighbourEntity);

if (CollisionDetection.AABBContainsPoint(neighbourCell.Position, neighbourCell.AABB,
transform.Position))
{
ref var neighbourContainer = ref _neighbours.Value.Get(neighbourEntity);
neighbourContainer.ContainingTransforms.Add(transformEntity);
}
}
}

Once.End();
}
Overall.End();

}
}
}
8 changes: 4 additions & 4 deletions Runtime/Systems/InsertTransformSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ namespace CellListsECS.Runtime.Systems
public class InsertTransformSystem : IEcsRunSystem
{
private readonly EcsFilterInject<Inc<InsertInCellLists, Transform>> _filter = default;
private readonly EcsFilterInject<Inc<Cell, CellNeighbours, TransformContainer>> _cellLists = default;
private readonly EcsFilterInject<Inc<Cell, CellNeighbours>> _cellLists = default;
private readonly EcsPoolInject<Transform> _transforms = default;
private readonly EcsPoolInject<InsertInCellLists> _commands = default;
private readonly EcsPoolInject<Cell> _cells = default;
private readonly EcsPoolInject<TransformContainer> _containers = default;
private readonly EcsPoolInject<CellNeighbours> _neighbours = default;

public void Run(IEcsSystems systems)
{
Expand All @@ -23,11 +23,11 @@ public void Run(IEcsSystems systems)
foreach (var cellEntity in _cellLists.Value)
{
ref var cell = ref _cells.Value.Get(cellEntity);
ref var container = ref _containers.Value.Get(cellEntity);
ref var neighbour = ref _neighbours.Value.Get(cellEntity);

if (CollisionDetection.AABBContainsPoint(cell.Position, cell.AABB, transform.Position))
{
container.All.Add(entity);
neighbour.ContainingTransforms.Add(entity);
}
}

Expand Down
8 changes: 3 additions & 5 deletions Samples~/CellDrawSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,26 @@ namespace CellListsECS.Samples
{
public class CellDrawSystem : IEcsRunSystem
{
private readonly EcsFilterInject<Inc<Cell, CellNeighbours, TransformContainer>> _filter = default;
private readonly EcsFilterInject<Inc<Cell, CellNeighbours>> _filter = default;
private readonly EcsPoolInject<Cell> _cells = default;
private readonly EcsPoolInject<Transform> _transforms = default;
private readonly EcsPoolInject<CellNeighbours> _neighbours = default;
private readonly EcsPoolInject<TransformContainer> _containers = default;

public void Run(IEcsSystems systems)
{
foreach (var entity in _filter.Value)
{
ref var cell = ref _cells.Value.Get(entity);
ref var neighbours = ref _neighbours.Value.Get(entity);
ref var container = ref _containers.Value.Get(entity);


foreach (var cellNeighbour in neighbours.All)
foreach (var cellNeighbour in neighbours.NeighboursEntities)
{
ref var neighbour = ref _cells.Value.Get(cellNeighbour);
Debug.DrawLine(cell.Position, neighbour.Position, Color.red);
}

foreach (var containingEntity in container.All)
foreach (var containingEntity in neighbours.ContainingTransforms)
{
ref var transform = ref _transforms.Value.Get(containingEntity);
Debug.DrawLine(cell.Position, transform.Position, Color.blue);
Expand Down
27 changes: 8 additions & 19 deletions Samples~/CollisionDetectionSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,55 +4,47 @@
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using Unity.Profiling;
using Transform = CellListsECS.Runtime.Components.Transform;

namespace CellListsECS.Samples
{
public class CollisionDetectionSystem : IEcsRunSystem
{
private readonly EcsWorldInject _collisionsWorld = "Collisions";
private readonly EcsFilterInject<Inc<Cell>> _cellsFilter = default;
private readonly EcsFilterInject<Inc<Cell, CellNeighbours>> _cellsFilter = default;
private readonly EcsPoolInject<Transform> _transforms = default;
private readonly EcsPoolInject<AABB> _aabbs = default;
private readonly EcsPoolInject<CellNeighbours> _neighbours = default;
private readonly EcsPoolInject<TransformContainer> _containers = default;
private readonly EcsPoolInject<Collision> _collisions = "Collisions";

private static readonly ProfilerMarker ListBuild = new(nameof(ListBuild));
private static readonly ProfilerMarker Job = new(nameof(Job));
private static readonly ProfilerMarker CollisionsWriting = new(nameof(CollisionsWriting));

public void Run(IEcsSystems systems)
{
foreach (var entity in _cellsFilter.Value)
{
ListBuild.Begin();
ref var neighbours = ref _neighbours.Value.Get(entity);
ref var cellContainer = ref _containers.Value.Get(entity);
var entities = new NativeList<(Transform, AABB, int)>(Allocator.TempJob);
var output = new NativeQueue<Collision>(Allocator.TempJob);

foreach (var transformEntity in cellContainer.All)

foreach (var transformEntity in neighbours.ContainingTransforms)
{
ref var transform = ref _transforms.Value.Get(transformEntity);
ref var aabb = ref _aabbs.Value.Get(transformEntity);
entities.Add((transform, aabb, transformEntity));
}

foreach (var neighbour in neighbours.All)
foreach (var neighbourEntity in neighbours.NeighboursEntities)
{
ref var neighbourContainer = ref _containers.Value.Get(neighbour);
ref var neighbour = ref _neighbours.Value.Get(neighbourEntity);

foreach (var transformEntity in neighbourContainer.All)
foreach (var transformEntity in neighbour.ContainingTransforms)
{
ref var transform = ref _transforms.Value.Get(transformEntity);
ref var aabb = ref _aabbs.Value.Get(transformEntity);
entities.Add((transform, aabb, transformEntity));
}
}
ListBuild.End();

Job.Begin();
var job = new CollisionDetectionJob()
{
Entities = entities,
Expand All @@ -61,9 +53,7 @@ public void Run(IEcsSystems systems)

job.Schedule(entities.Length, 32).Complete();

Job.End();

CollisionsWriting.Begin();
while (output.Count > 0)
{
var collision = output.Dequeue();
Expand All @@ -74,10 +64,9 @@ public void Run(IEcsSystems systems)

entities.Dispose();
output.Dispose();
CollisionsWriting.End();
}
}

[BurstCompile]
public struct CollisionDetectionJob : IJobParallelFor
{
Expand Down
Loading

0 comments on commit cf87945

Please sign in to comment.