Search Unity

Intermittent issues with accessing entities in ComponentGroup.GetEntityArray()

Discussion in 'Entity Component System' started by LukePammant, Nov 14, 2018.

  1. LukePammant

    LukePammant

    Joined:
    Mar 10, 2015
    Posts:
    50
    I'm having a strange issue when trying to get an entity via entities when using ComponentGroups. Just logging out the entity causes intermittent issues:
    After modifying the code in any way (even just adding a debug line) the first run works fine.
    If I stop the game and run again it will sometimes either log an entities with an index in the 90,000's+ or will throw a null reference exception. It bounce back and forth between these issues every time I run. Here is the exception:

    NullReferenceException: Object reference not set to an instance of an object
    Unity.Entities.ComponentChunkIterator.UpdateCacheToCurrentChunk (Unity.Entities.ComponentChunkCache& cache, System.Boolean isWriting, System.Int32 indexInComponentGroup) (at <49b513de354643a2a0a32b80e091e5a5>:0)
    Unity.Entities.ComponentChunkIterator.MoveToEntityIndexAndUpdateCache (System.Int32 index, Unity.Entities.ComponentChunkCache& cache, System.Boolean isWriting) (at <49b513de354643a2a0a32b80e091e5a5>:0)
    Unity.Entities.EntityArray.get_Item (System.Int32 index) (at <49b513de354643a2a0a32b80e091e5a5>:0)
    AttackSystem.OnUpdate () (at Assets/Scripts/ECS/Systems/Shooting/AttackSystem.cs:33)
    Unity.Entities.ComponentSystem.InternalUpdate () (at <49b513de354643a2a0a32b80e091e5a5>:0)
    Unity.Entities.ScriptBehaviourManager.Update () (at <49b513de354643a2a0a32b80e091e5a5>:0)
    Unity.Entities.ScriptBehaviourUpdateOrder+DummyDelagateWrapper.TriggerUpdate () (at <49b513de354643a2a0a32b80e091e5a5>:0)


    The entitiy debugger shows the correct Entity (14) in the attack system:
    upload_2018-11-14_9-28-23.png
    (
    side note: why does that 2nd component group get 3 'ammo' tags? I see this a lot.)

    Here is the attack system code:
    Code (CSharp):
    1. using Unity.Entities;
    2. using UnityEngine;
    3.  
    4. public struct AttackingTag : IComponentData { }
    5.  
    6. public class AttackSystem : ComponentSystem
    7. {
    8.     private ComponentGroup _nonAttackingGroup;
    9.     private ComponentGroup _attackingGroup;
    10.     private readonly AttackingTag _attacking = new AttackingTag();
    11.  
    12.     protected override void OnCreateManager()
    13.     {
    14.         _nonAttackingGroup = GetComponentGroup(new EntityArchetypeQuery()
    15.         {
    16.             All = new ComponentType[] { typeof(Ammo) },
    17.             None = new ComponentType[] { typeof(AttackingTag) }
    18.         });
    19.  
    20.         _attackingGroup = GetComponentGroup(typeof(Ammo), typeof(AttackingTag));
    21.     }
    22.  
    23.     protected override void OnUpdate()
    24.     {
    25.         var nonAttackingEntities = _nonAttackingGroup.GetEntityArray();
    26.  
    27.         var mouseDown = Input.GetMouseButton(0);
    28.         if (mouseDown)
    29.         {
    30.             for (var i = 0; i < nonAttackingEntities.Length; i++)
    31.             {
    32.                 // The Debug sometimes throws null reference exception, sometimes logs out an entity with a huge index number, sometimes logs the correct player entity (14) and works
    33.                 Debug.Log(nonAttackingEntities[i]);
    34.             }
    35.         }
    36.     }
    37. }
    This was working fine when I was using [Inject] but I've been trying to move away from that since it is being deprecated.
     
    Last edited: Nov 15, 2018
  2. temps12

    temps12

    Joined:
    Nov 28, 2014
    Posts:
    41
    When you use the EntityManager to add or remove components you invalidate your arrays of entities. Use a command buffer instead and queue up your adds and removals. PostUpdateCommands is a command buffer that will playback your commands after the system has updated. So to fix your issue, use PostUpdateCommands.AddComponent and PostUpdateCommands.RemoveComponent instead of the EntityManager.
     
  3. LukePammant

    LukePammant

    Joined:
    Mar 10, 2015
    Posts:
    50
    I have tried that too. It breaks before it even reaches that line. It breaks just reading at the Debug.Log(entities); line before I even do Add or Remove component. I tried PostUpdateCommands, BarrierSystems, and EntityManager and get the same strange intermittent issues. The thing that gets me is that it's intermittent. It works after a fresh recompile but doesn't work on every subsequent 'play'.
     
    Last edited: Nov 14, 2018
  4. temps12

    temps12

    Joined:
    Nov 28, 2014
    Posts:
    41
    hmm, do you perhaps need to set the "Any" array in EntityArchetypeQuery to an empty array instead of null?
     
  5. LukePammant

    LukePammant

    Joined:
    Mar 10, 2015
    Posts:
    50
    That doesn't seem to fix it either.

    I've been doing some more reading and it looks like I might have to bite the bullet and go with chunk iteration.
     
  6. Deleted User

    Deleted User

    Guest

    Change

    Code (CSharp):
    1. _nonAttackingGroup = GetComponentGroup(new EntityArchetypeQuery()
    2.         {
    3.             All = new ComponentType[] { typeof(Ammo) },
    4.             None = new ComponentType[] { typeof(AttackingTag) }
    5.         });
    6.  
    To

    Code (CSharp):
    1. _nonAttackingGroup = GetComponentGroup(typeof(Ammo), ComponentType.SubtractiveComponent<AttackingTag>());
    2.  
     
    LukePammant likes this.
  7. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    He's trying to move away from code that will be removed so I don't think you should be suggesting he changes back.

    But yeah the issue is GetEntityArray() (and GetComponentDataArray()) does not work when you are passing an archetype query - you're meant to be doing chunk iteration.
     
    LukePammant and 5argon like this.
  8. Deleted User

    Deleted User

    Guest

    I am fixing the issue. Nothing else. When they will introduce the new simillar API he will just change one line of code. And I didn't suggest anything that will be removed though. ComponentGroup won't be removed.
     
    Last edited by a moderator: Dec 1, 2018
    LukePammant likes this.