Arch
Arch copied to clipboard
`Debug.Assert` for operations on entities and dead entities.
Encountered another issue when investigating https://github.com/genaray/Arch/issues/109
using Arch.Core.CommandBuffer;
using Arch.Core.Utils;
using Arch.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Arch.Core.Extensions;
namespace ConsoleTestApp;
internal class ArchDuplicatedResults
{
private static int _index;
private static World _world;
private static QueryDescription _queryDesc;
private static QueryDescription _queryDesc1;
private static QueryDescription _queryDesc2;
public static void Execute()
{
_world = World.Create();
_queryDesc = new QueryDescription().WithAll<Base, Component1>();
_queryDesc1 = new QueryDescription().WithAll<Component2>();
_queryDesc2 = new QueryDescription().WithAll<Component3>();
var list = new List<All>();
for(var i = 0; i < 100; i++)
list.Add(SpawnEntity());
var res1 = CheckQuery();
if (res1 != 100)
Console.WriteLine("hmm1");
for (var i = 0; i < 100; i += 10)
list[i].Base.Ref.Entity.Remove<Component2>();
var res2 = CheckQuery();
if (res2 != 100)
Console.WriteLine("hmm2");
for (var i = 0; i < 100; i += 10)
_world.Destroy(list[i].Base.Ref.Entity);
var res3 = CheckQuery();
if (res3 != 90)
Console.WriteLine("hmm3");
for (var i = 0; i < 100; i += 10)
{
var cur = list[i];
var c3 = new Component3() { Val = cur.Component1.Val };
cur.Component3 = c3;
_world.Add(cur.Base.Ref.Entity, in c3);
}
var res4 = CheckQuery();
if (res4 != 90)
Console.WriteLine("hmm4");
}
private static int CheckQuery()
{
var queryRes = new List<(Arch.Core.EntityReference, Base, Component1)>();
var query = _world.Query(in _queryDesc);
foreach (ref var chunk in query)
foreach (var index in chunk)
{
ref readonly var e = ref chunk.Entity(index);
if (!e.IsAlive())
continue;
if (!e.Has<Base, Component1>())
continue;
var refs = e.Get<Base, Component1>();
queryRes.Add((e.Reference(), refs.t0, refs.t1));
}
foreach (var (entityReference, entity, component) in queryRes)
{
if (entityReference.Entity.Id != entity.Ref.Entity.Id)
{
Console.WriteLine("Hmm");
continue;
}
}
return queryRes.Count;
}
private static All SpawnEntity()
{
var e = _world.Create();
var entityRef = e.Reference();
var index = ++_index;
var b = new Base() { Ref = entityRef };
var c1 = new Component1() { Val = index };
var c2 = new Component2() { Val = index.ToString() };
_world.Add(e, in b);
_world.Add(e, in c1);
_world.Add(e, in c2);
return new All
{
Base = b,
Component1 = c1,
Component2 = c2
};
}
class All
{
public Base Base { get; init; }
public Component1 Component1 { get; set; }
public Component2 Component2 { get; set; }
public Component3 Component3 { get; set; }
}
class Base
{
public EntityReference Ref { get; init; }
}
class Component1
{
public int Val { get; set; }
}
class Component2
{
public string Val { get; set; }
}
class Component3
{
public double Val { get; set; }
}
}
Runing ArchDuplicatedResults.Execute() produced null ptr ex in line _world.Add(cur.Base.Ref.Entity, in c3);
I assume that because give Entity was destroyed before.
So behavior is ok just Error could give more details cause NulltPtr looks like unhandled situation
I assume that because give Entity was destroyed before.
So behavior is ok just Error could give more details cause NulltPtr looks like unhandled situation
Yep, operations on dead entities can result in such exceptions.
I will add Debug.Asserts to inform the user that the operation is not valid since the entity is dead.