I have a system that runs before BeginSimulationECB that destroys some entities. My other systems run after TransformSystemGroup. After the entities are destroyed, other entities which reference the destroyed entities in their IComponentData never recover (entity == Entity.Null) doesn’t work and I get
Unfortunately the entity == Entity.Null check doesn’t work for destroyed entities. You need to either use EntityManager.Exists or pass a ComponentDataFromEntity into your job and use cdfe.Exists. I think the better solution if possible is to ensure that your entities never get destroyed until the very end of the frame so it’s never possible to accidentally access a destroyed entity. You could add a Disabled earlier in the frame so it doesn’t get picked up by other systems, then include that in a query at the end of the frame when you’re destroying it.
I’d love to see Unity give is some better ways of handling this case. Having to deal with an entity being destroyed earlier in the frame doesn’t seem like that unusual of a use case, but as it is right now we get absolutely not help on how to deal with it, so the best solution seems to be “Don’t do it”.
So according to what you said if I run my destroy system after the other systems there shouldn’t be any problem, since they will check for null on the next frame.
In my current situation null check does not work no matter how many frames have passed since destroy.
Entity is just handle. It store id (int64) of entity and Entity.Null is just id = 0
You never will have your id to become 0 until you set it to 0, no matter how many frames will pass.
The only way to know that you EntityId is id of real live entity is call EntityManager.Exists
Sorry for the confusion, my point about destroying at the end of the frame is only relevant for referencing entities via command buffers. Like Jes said, if you’re dealing with a component that references another entity, you always need to use EntityManager/cdfe.Exists
Nice to see I’m not the only one bothered by this. Anyone trying to make at least a prototype of a game will face this issue and it is frustrating. I like your solution too (though my problem is a bit different in this case).
Most entities are destroyed in a single system in our project - at least all that can be reference by another entity.
If we just randomly destroyed entities it would be a complete mess as we have something like 2000 jobs now.
Yes. And Multiple Event Systems make it worst. Some of the events will eventually be delayed to the next frame, where a target entity could have been destroyed. Check for Entity existence is need when processing Event.
Actually there nothing new in ECS compared to MonoBehaviours
MB.Destroy is delayed to the end of frame, in ECS better to do the same i.e. never destroy inplace
Reference to any GO or MB never magically become null if some code destroy go, we need to check object live if(myObj){...} to work with it, in ECS we have same thing, but have slightly more control of it
This is simply false as others mentioned you need to be careful with ecb and checking for null, when to destroy entities and stuff. When working with Monobehaviour simple gameobject != null will never fail you