-
@friflo edit: format code as C# I implemented this version in Parallel and without, dont see any difference in "ms". Did i implement it wrongly? protected override void OnUpdate()
{
_spatialHash.Clear();
_entitiesToDelete.Clear();
// Alle Entitäten in das Spatial Hashing-System einfügen
Query.ForEachEntity((ref CircleShape circle, ref Position2D position, Entity entity) =>
{
_spatialHash.Insert(entity.Id, position.Value);
});
CommandBuffer cb = _entityStore.GetCommandBuffer();
var queryJob = Query.ForEach((circles, positions, entities) =>
{
for (int i = 0; i < circles.Length; i++)
{
var pos = positions[i];
var circ = circles[i];
var ent = entities[i];
var possibleCollisions = _spatialHash.Retrieve(pos.Value, circ.Radius);
foreach (var otherEntityId in possibleCollisions)
{
if (ent == otherEntityId || _entitiesToDelete.Contains(ent) ||
_entitiesToDelete.Contains(otherEntityId))
continue;
var otherEntity = _entityStore.GetEntityById(otherEntityId);
var otherCircle = otherEntity.GetComponent<CircleShape>();
var otherPosition = otherEntity.GetComponent<Position2D>().Value;
// Prüfe, ob die Layer gemäß der Kollisionsmatrix kollidieren dürfen
if (!CollisionLayerMatrix.CanCollide(circ.Layer, otherCircle.Layer))
continue;
if (IsColliding(pos.Value, circ.Radius, otherPosition, otherCircle.Radius))
{
bool thisEntityHasAvoid = !circ.IsTrigger;
bool otherEntityHasAvoid = !otherCircle.IsTrigger;
if (thisEntityHasAvoid && otherEntityHasAvoid)
{
// Überlappung verhindern
ResolveCollision(ref pos.Value, circ.Radius, ref otherPosition, otherCircle.Radius);
// Aktualisierte Positionen setzen
positions[i].Value = pos.Value;
otherEntity.GetComponent<Position2D>().Value = otherPosition;
}
else if (thisEntityHasAvoid && !otherEntityHasAvoid)
{
// Andere Entität zur Löschung markieren
_entitiesToDelete.Add(otherEntityId);
cb.DeleteEntity(otherEntityId);
}
else if (!thisEntityHasAvoid && otherEntityHasAvoid)
{
// Diese Entität zur Löschung markieren
_entitiesToDelete.Add(ent);
cb.DeleteEntity(ent);
}
}
}
}
});
queryJob.JobRunner = _runner;
queryJob.RunParallel();
cb.Playback();
} |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 2 replies
-
Hi @MaansenV, I need some numbers to analyze this. This log only once: Console.WriteLine($"JobRunner - thread count: {runner.ThreadCount}");
Console.WriteLine($"QueryJob - MinParallelChunkLength: {queryJob.MinParallelChunkLength}");
Console.WriteLine($"QueryJob - ParallelComponentMultiple: {queryJob.ParallelComponentMultiple}"); and a couple of these logs after calling Console.WriteLine(root.GetPerfLog());
stores: 1 last ms sum ms updates last mem sum mem entities
--------------------- -------- -------- -------- -------- -------- --------
Systems [2] 0.079 3.074 10 128 1392
| ScaleSystem 0.039 1.789 10 64 696 10000
| PositionSystem 0.039 1.278 10 64 696 10000 |
Beta Was this translation helpful? Give feedback.
-
Some notes to you code snippet. _spatialHash.Insert()To enhance performance you should you Span<>'s: foreach (var (circles, positions, entities) in Query.Chunks)
{
spatialHash.Insert(circles.Span, entities.Ids)
} CommandBufferEach QuerySytem<> has a You should use this instead of creating your own. CommandBuffer cb = _entityStore.GetCommandBuffer();
...
cb.Playback(); The parent group calls Inner loops: circles / collisionsMaybe optimization potential - but after applying the notes above. |
Beta Was this translation helpful? Give feedback.
-
here is the data u requested. i dont really need 5000 entities for the collision System, but it was just a test to see how it scales. |
Beta Was this translation helpful? Give feedback.
Thx,
The interesting numbers are:
16 threads => 5000 / 16 = 312 entities per chunk.
Assuming all entities are in a single Archetype.
Using multi threading in
RunParallel()
requires:entities per chunk must be >
MinParallelChunkLength
.If the threshold is not met
Query.ForEach(...)
is executed single threaded.So lower
MinParallelChunkLength
to 100 or 10.In your case the computation in
Query.ForEach(...)
is significant.The reason for a threshold is to avoid multi treading if the cost for thread synchronization is too high.
It is about 1 - 2 micro seconds per thread - an eternity :)