Search Unity

  1. Unity 2020.1 has been released.
    Dismiss Notice
  2. We are looking for feedback on the experimental Unity Safe Mode which is aiming to help you resolve compilation errors faster during project startup.
    Dismiss Notice
  3. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

The NativeArray has been deallocated - Hybrid ECS

Discussion in 'Data Oriented Technology Stack' started by Bhakti_GL1, Dec 18, 2018.

  1. Bhakti_GL1

    Bhakti_GL1

    Joined:
    Jul 4, 2018
    Posts:
    17
    So today I got an "InvalidOperationException: The NativeArray has been deallocated, it is not allowed to access it" error in one of my componentsystem.

    I have GameManager.cs that instantiates player and enemies when the game starts. There's nothing wrong when there's only 1 enemy, but after I set max enemy to more than one, "that" error occurs. I have been gathering some information from other posts in this forum and I think that the "Enemy's Instantiate step" on the GameManager is the source of this problem (and yes, please correct me if I am wrong, I'm just a new guy here).

    I am using Hybrid ECS. All of my entities have Parent component (for Pure ECS & Job system) and Child component (for physics and animation using Hybrid ECS & Component System). So when I instantiate new Entity, I always add the Entity component into List (for syncing Parent and Child), yes I know it's complicated but I think that is my "simplest way" to made Job system, Unity physics, and animation in one place. Btw I would be very thankful if u give me any other "simplest ways".

    Here is the "Enemy's Instantiate step" on the GameManager
    Code (CSharp):
    1. static void AddBee (int maxEnemy)
    2.         {
    3.             EntityManager manager = World.Active.GetOrCreateManager<EntityManager>();
    4.  
    5.             GameObject beePrefab = settings.beeEnemyPrefab;
    6.             float horBound = settings.horizontalBound;
    7.             float verBound = settings.verticalBound;
    8.  
    9.             for (int i=0; i<maxEnemy; i++)
    10.             {
    11.                 float xVal = Random.Range(-horBound, horBound);
    12.                 float zVal = Random.Range(-verBound, verBound);
    13.  
    14.                 // PARENT
    15.                 GameObject beeGO = GameObject.Instantiate(beePrefab, new Vector3(xVal, 0f, zVal), Quaternion.identity);
    16.                 GameObjectEntity beeGOEntity = beeGO.GetComponent<GameObjectEntity>();
    17.                 beeGOEntity.enabled = true;
    18.                 Entity beeEntity = beeGOEntity.Entity;
    19.  
    20.                 parentEntitiesInGame.Add(beeEntity);
    21.                 int currentParentEntityIndex = parentEntitiesInGame.Count-1;
    22.  
    23.                 manager.SetComponentData(beeEntity, new Parent { EntityIndex = currentParentEntityIndex });
    24.  
    25.                 // CHILD
    26.                 ChildComponent childComponent = beeGO.GetComponentInChildren<ChildComponent>();
    27.                 GameObjectEntity beeChildGOEntity = childComponent.GetComponent<GameObjectEntity>();
    28.  
    29.                 childEntitiesInGame.Add(beeChildGOEntity);
    30.                 int currentChildEntityIndex = childEntitiesInGame.Count-1;
    31.  
    32.                 childComponent.EntityIndex = currentChildEntityIndex;
    33.  
    34.                 entitiesAnimationToggle.Add(0);
    35.                 entitiesIdleLoopAnimationChecker.Add(0);
    36.  
    37.                 beeChildGOEntity.enabled = true;
    38.             }
    39.         }
    And here is the componentsystem that "doing enemy stuff" ;)
    Error on line 23.

    Code (CSharp):
    1. public struct Data
    2.         {
    3.             public readonly int Length;
    4.             [ReadOnlyAttribute] public EntityArray entity;
    5.             [ReadOnlyAttribute] public ComponentDataArray<Bee> Bee;
    6.             public ComponentDataArray<EnemyAIDirection> EnemyAIDirection;
    7.             [ReadOnlyAttribute] public ComponentDataArray<Position> Position;
    8.             [ReadOnlyAttribute] public ComponentDataArray<Parent> Parent;
    9.         }
    10.         [InjectAttribute] Data data;
    11.  
    12.         float3 float3Zero = float3.zero;
    13.         float deltaTime;
    14.  
    15.         protected override void OnUpdate ()
    16.         {
    17.             EntityCommandBuffer commandBuffer = PostUpdateCommands;
    18.  
    19.             deltaTime = Time.deltaTime;
    20.  
    21.             for (int i=0; i<data.Length; i++)
    22.             {
    23.                 Entity entity = data.entity[i];
    24.                 Bee bee = data.Bee[i];
    25.                 EnemyAIDirection enemyAIDirection = data.EnemyAIDirection[i];
    26.                 Position position = data.Position[i];
    27.                 Parent parent = data.Parent[i];
    28.                 commandBuffer.RemoveComponent<EnemyAIDirection>(entity);
    29.  
    30.                 // Other "Fun" Stuff
    31.             }
    32.         }
    33.  
    I'm stuck and stressed out for a couple of hours already. I would be glad if u help me fix these error, thank u very much! ;)
     
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    2,383
    What's the other fun stuff
     
    5argon likes this.
  3. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,029
    Yep I'm interested too, seems you made structural changes in this area
     
  4. Bhakti_GL1

    Bhakti_GL1

    Joined:
    Jul 4, 2018
    Posts:
    17
    Alrighty then, here is my "fun" stuff :D

    Code (CSharp):
    1.  
    2.                 // Other "Fun" Stuff
    3.  
    4.                 float3 targetPos = float3Zero;
    5.                 int entityIndex = parent.EntityIndex;
    6.                 GameObjectEntity entityGO = childEntitiesInGame[entityIndex];
    7.                 GameObject childGO = entityGO.gameObject;
    8.  
    9. #region Nav Mesh Direction
    10.                 float moveRange = bee.MoveRange;
    11.                 float posX = position.Value.x;
    12.                 float posZ = position.Value.z;
    13.                 float randomX = UnityRandom.Range(posX - moveRange, posX + moveRange);
    14.                 float randomZ = UnityRandom.Range(posZ - moveRange, posZ + moveRange);
    15.                 targetPos = new float3(randomX, 0f, randomZ);
    16.                
    17.                 // enemyNavMeshData.TargetPosition = targetPos;
    18.                 childGO.AddComponent<NavMeshEventComponent>().Destination = targetPos;
    19.                 entityGO.enabled = false;
    20.                 entityGO.enabled = true;
    21. #endregion
    This fun stuff is a Nav Mesh code for enemy AI. It only adds NavMeshEventComponent to enemy's child.
    And yes, I am accepting some nice idea for these AI codes. Thank you very much :)
     
  5. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    2,383
    And this is why you need to include all your code, this is your issue

    Code (CSharp):
    1. entityGO.enabled = false;
    2. entityGO.enabled = true;
    This destroys then creates an entity, invalidating all your ComponentDataArrays
     
    Bhakti_GL1 and eizenhorn like this.
  6. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,029
    You're faster :) 5AM by my timezone, I'm slept at tis time, not fair :D
     
    Bhakti_GL1 likes this.
  7. Bhakti_GL1

    Bhakti_GL1

    Joined:
    Jul 4, 2018
    Posts:
    17
    Thank you very much, now the error is gone, and I have to change my code a bit

    btw that disabling-enabling the GameObjectEntity is my "tricky way" to refresh the "EntityManager" (I don't know what it called) because it's not live updating the GameObjectEntity when you adding or removing a component to them. Do you know the correct way about how to refresh the manager? Thank you :)
     
  8. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,029
    Code (CSharp):
    1.  
    2. protected virtual void OnEnable()
    3. {
    4. EntityManager entityManager;
    5. Entity entity;
    6. if (
    7. World.Active != null
    8. && TryGetEntityAndManager(out entityManager, out entity)
    9. && !entityManager.HasComponent(entity, GetComponentType()) // in case GameObjectEntity already added
    10. )
    11. entityManager.AddComponent(entity, GetComponentType());
    12. }
    13.  
    14. protected virtual void OnDisable()
    15. {
    16. if (!gameObject.activeInHierarchy) // GameObjectEntity will handle removal when Entity is destroyed
    17. return;
    18. EntityManager entityManager;
    19. Entity entity;
    20. if (CanSynchronizeWithEntityManager(out entityManager, out entity))
    21. entityManager.RemoveComponent(entity, GetComponentType());
    22. }
    23.  
    24. internal bool TryGetEntityAndManager(out EntityManager entityManager, out Entity entity)
    25. {
    26. entityManager = null;
    27. entity = Entity.Null;
    28. var gameObjectEntity = GetComponent<GameObjectEntity>();
    29. if (gameObjectEntity == null)
    30. return false;
    31. if (gameObjectEntity.EntityManager == null)
    32. return false;
    33. if (!gameObjectEntity.EntityManager.Exists(gameObjectEntity.Entity))
    34. return false;
    35. entityManager = gameObjectEntity.EntityManager;
    36. entity = gameObjectEntity.Entity;
    37. return true;
    38. }
    39.  
    40. internal bool CanSynchronizeWithEntityManager(out EntityManager entityManager, out Entity entity)
    41. {
    42. return TryGetEntityAndManager(out entityManager, out entity)
    43. && entityManager.HasComponent(entity, GetComponentType());
    44. }
    45.  
     
    Bhakti_GL1 likes this.
  9. Bhakti_GL1

    Bhakti_GL1

    Joined:
    Jul 4, 2018
    Posts:
    17
    Thank you eizenhorn, you're my hero :D

    btw I have to put those code on every gameobject that has GameObjectEntity component, and let them synchronizing themselves with the EntityManager so I don't have to use "disabling-enabling jutsu" to every destroyed/instantiated GameObjectEntity, right?
     
  10. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,029
    This is what GameObjectEntity does, it's GameObjectEntity source code.
     
  11. Bhakti_GL1

    Bhakti_GL1

    Joined:
    Jul 4, 2018
    Posts:
    17
    Wait I don't get it, what should I do? I don't understand :(

    Compared with yours GameObjectEntity, here are my default GameObjectEntity source code :
    Code (CSharp):
    1. #region Assembly Unity.Entities.Hybrid, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
    2. // <in-memory assembly>
    3. #endregion
    4.  
    5. using UnityEngine;
    6.  
    7. namespace Unity.Entities
    8. {
    9.     [DisallowMultipleComponent]
    10.     [ExecuteInEditMode]
    11.     public class GameObjectEntity : MonoBehaviour
    12.     {
    13.         public GameObjectEntity();
    14.  
    15.         public EntityManager EntityManager { get; }
    16.         public Entity Entity { get; }
    17.  
    18.         public static Entity AddToEntityManager(EntityManager entityManager, GameObject gameObject);
    19.         public void CopyAllComponentsToEntity(EntityManager entityManager, Entity entity);
    20.         protected virtual void OnDisable();
    21.         protected virtual void OnEnable();
    22.     }
    23. }
     
  12. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,029
    Because you not decompile it full. Just check entities package folder and you'll see sources.
     
  13. Bhakti_GL1

    Bhakti_GL1

    Joined:
    Jul 4, 2018
    Posts:
    17
    Alright I found the GameObjectEntity source code on my entities package folder

    But how to refresh the Entity component in EntityDebugger of any GameObjectEntity when I added or destroyed one of its component? Because the Entities are not updating automatically right now. I just couldn't figure it out, Thank you btw
     
  14. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,029
    Just look what does in OnEnable\Disable and you understand :)
     
  15. Bhakti_GL1

    Bhakti_GL1

    Joined:
    Jul 4, 2018
    Posts:
    17
    Nope, It's hard for me to understand what GameObjectEntity does when they are on OnEnable and OnDisable "state". I tried adding the modified component of GameObjectEntity's Entity on the EntityManager using:
    manager.AddComponent(GameObjectEntity.Entity, typeof (ComponentType));

    But then "NullReferenceException" error occurs. I have to get the ComponentType on its Entity to fix that error. (doing "GetComponent" on loop, It's much worse I think)
    And btw adding the modified GameObjectEntity component to EntityManager still cause deallocated NativeArray as same as "disabling-enabling jutsu".

    If I add the GameObjectEntity to EntityManager using:
    GameObjectEntity.AddToEntityManager(EntityManager, GameObject);

    It adds new Entity on EntityManager everytime I modified the Component of GameObjectEntity, (yes I know because it's "AddToEntityManager", but I have to prove it by myself :D )

    And then I'm stuck,

    But Thank you btw for your help @eizenhorn , now I'm quite understand about ECS a little bit
     
  16. Bhakti_GL1

    Bhakti_GL1

    Joined:
    Jul 4, 2018
    Posts:
    17
    After a couple of some trial and error implementation, I have come with this :
    Code (CSharp):
    1.  
    2.  
    3.                 entityGO.enabled = false;
    4.                 entityGO.enabled = true;
    5.  
    6.                 // data = new Data(); //1. Reset the loop (I think)
    7.                 // break; //2. Break the loop
    8.                 // return; //3. Break out from the entire function
    9.  
    I just "reset" the Struct that used in ComponentSystem.
    Those three lines of code currently fix my problem, but I know it's only for now. (and yes I still using "disabling-enabling jutsu")
     
  17. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,029
    It will in any case with EntityManager, because it's structural chages )
     
  18. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,029
    You can use UpdateInjectedComponentGroups(), but remember it's slow, but fine on small data amount.
     
    Bhakti_GL1 likes this.
  19. Bhakti_GL1

    Bhakti_GL1

    Joined:
    Jul 4, 2018
    Posts:
    17
    Thank you very much, maybe it's much better than break out from the loop ( I have no idea :D )
     
unityunity