Search Unity

Using HybridECS, getting this: The NativeArray has been deallocated, it is not allowed to access it.

Discussion in 'Entity Component System' started by larssonmartin1998, Jul 4, 2018.

  1. larssonmartin1998

    larssonmartin1998

    Joined:
    Dec 12, 2017
    Posts:
    11
    I'm building my game using default monobehaviour and hybrid ECS where it makes sense (where the components is used on multiple objects). However, I'm now getting this error in two of my scripts: The NativeArray has been deallocated, it is not allowed to access it.

    The enemy spawner gets the error on line 57, and the fireball script gets it on line 89. So it's when I'm trying to access the entitiy in the entities array, makes sense that it doesn't work if the "NativeArray has been deallocated". However, why is it deallocated, what am I doing wrong?

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Unity.Entities;
    5.  
    6. public class EnemySpawner : MonoBehaviour
    7. {
    8.     public float spawnDelay = 5f;
    9.  
    10.     [HideInInspector]
    11.     public PoolManager.PoolType enemyToSpawn;
    12.     [HideInInspector]
    13.     public float elapsed = 0f;
    14. }
    15.  
    16. class EnemySpawnerSystem : ComponentSystem
    17. {
    18.     private PoolManager poolManager;
    19.     private GameManager gameManager;
    20.     private List<PoolManager.PoolType> possibleEnemies;
    21.  
    22.     struct Components
    23.     {
    24.         public Transform transform;
    25.         public EnemySpawner spawner;
    26.     }
    27.  
    28.     protected override void OnStartRunning()
    29.     {
    30.         //base.OnStartRunning();
    31.  
    32.         poolManager = PoolManager.instance;
    33.         gameManager = GameManager.instance;
    34.         possibleEnemies = new List<PoolManager.PoolType>();
    35.  
    36.         var entities = GetEntities<Components>();
    37.         for (int entityIndex = 0; entityIndex < entities.Length; ++entityIndex)
    38.         {
    39.             var e = entities[entityIndex];
    40.             e.spawner.elapsed = Random.Range(0f, e.spawner.spawnDelay - 2f);
    41.         }
    42.  
    43.         possibleEnemies.Add(PoolManager.PoolType.POOL_ORC_WARRIOR_A);
    44.         possibleEnemies.Add(PoolManager.PoolType.POOL_ORC_WARRIOR_B);
    45.         possibleEnemies.Add(PoolManager.PoolType.POOL_ORC_WARRIOR_C);
    46.     }
    47.  
    48.     protected override void OnUpdate()
    49.     {
    50.         float deltaTime = Time.deltaTime;
    51.         var entities = GetEntities<Components>();
    52.  
    53.         if (gameManager.numEnemiesToSpawn > 0)
    54.         {
    55.             for (int entityIndex = 0; entityIndex < entities.Length; ++entityIndex)
    56.             {
    57.                 var e = entities[entityIndex];
    58.  
    59.                 if (e.spawner.elapsed >= e.spawner.spawnDelay)
    60.                 {
    61.                     SpawnEnemy(e.spawner);
    62.                 }
    63.  
    64.                 e.spawner.elapsed += deltaTime;
    65.             }
    66.         }
    67.     }
    68.  
    69.     private void SpawnEnemy(EnemySpawner spawner)
    70.     {
    71.         spawner.enemyToSpawn = possibleEnemies[Random.Range(0, possibleEnemies.Count)];
    72.         poolManager.SpawnFromPool(spawner.enemyToSpawn, spawner.transform.position + Random.insideUnitSphere, spawner.transform.rotation);
    73.         spawner.elapsed = 0f;
    74.         gameManager.numEnemiesToSpawn--;
    75.     }
    76. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Events;
    5. using Unity.Entities;
    6.  
    7. public class Fireball : ProjectileBase
    8. {
    9.     [Header("Settings")]
    10.     public float destroyDelay = 0.35f;
    11.     public float damage = 30f;
    12.    
    13.     [Header("Link Settings")]
    14.     public ParticleSystem fireballParticles;
    15.     public ParticleSystem smokeParticles;
    16.  
    17.     [HideInInspector]
    18.     public bool wantsRemove = false;
    19.     [HideInInspector]
    20.     public float destroyCounter = 0f;
    21.  
    22.     private PoolManager poolManager;
    23.     private EventManager eventManager;
    24.  
    25.     private void Start()
    26.     {
    27.         poolManager = PoolManager.instance;
    28.         eventManager = EventManager.instance;
    29.     }
    30.  
    31.     public void OnDisable()
    32.     {
    33.         destroyCounter = 0f;
    34.         wantsRemove = false;
    35.         movedUnits = 0f;
    36.     }
    37.  
    38.     private void OnTriggerEnter(Collider other)
    39.     {
    40.         if (((1 << other.gameObject.layer) & hitLayer) != 0)
    41.         {
    42.             Health otherHealth = other.GetComponent<Health>();
    43.             otherHealth.TakeDamage(damage);
    44.             Explode();
    45.         }
    46.     }
    47.  
    48.     public void Explode()
    49.     {
    50.         if (wantsRemove)
    51.         {
    52.             return;
    53.         }
    54.  
    55.         eventManager.TriggerEvent("FireballExplosion");
    56.         poolManager.SpawnFromPool(PoolManager.PoolType.POOL_EXPLOSION, transform.position, transform.rotation);
    57.         fireballParticles.Stop();
    58.         smokeParticles.Stop();
    59.         wantsRemove = true;
    60.     }
    61. }
    62.  
    63. class FireballSystem : ComponentSystem
    64. {
    65.     private EventManager eventManager;
    66.     private PoolManager poolManager;
    67.  
    68.     struct Components
    69.     {
    70.         public Transform transform;
    71.         public Fireball projectile;
    72.     }
    73.  
    74.     protected override void OnStartRunning()
    75.     {
    76.         base.OnStartRunning();
    77.  
    78.         eventManager = EventManager.instance;
    79.         poolManager = PoolManager.instance;
    80.     }
    81.  
    82.     protected override void OnUpdate()
    83.     {
    84.         float deltaTime = Time.deltaTime;
    85.         var entities = GetEntities<Components>();
    86.  
    87.         for (int entityIndex = 0; entityIndex < entities.Length; ++entityIndex)
    88.         {
    89.             var e = entities[entityIndex];
    90.             if (e.projectile.movedUnits >= e.projectile.range)
    91.             {
    92.                 e.projectile.Explode();
    93.  
    94.                 if (e.projectile.destroyCounter >= e.projectile.destroyDelay)
    95.                 {
    96.                     e.projectile.gameObject.SetActive(false);
    97.                 }
    98.                 e.projectile.destroyCounter += deltaTime;
    99.                
    100.                 continue;
    101.             }
    102.  
    103.             Vector3 movement = e.projectile.direction * e.projectile.movementSpeed * deltaTime;
    104.             Vector3 deltaMovement = e.transform.position + movement - e.transform.position;
    105.  
    106.             e.transform.position += movement;
    107.             e.projectile.movedUnits += Mathf.Abs(deltaMovement.x) + Mathf.Abs(deltaMovement.y) + Mathf.Abs(deltaMovement.z);
    108.         }
    109.     }
    110. }
     
  2. dartriminis

    dartriminis

    Joined:
    Feb 3, 2017
    Posts:
    157
    In your fireballSystem and possibly poolManager.SpawnFromPool, you are activating/disabling game objects. If those game objects have a GameObjectEntity attached, then doing this is creating and destroying entities, which in turn is invalidating your ComponentGroup arrays.

    The way around this is to make a sort of command list from your loops, then spawn/SetActive everything once you're done looping over everything. Much like the EntityCommandBuffer.
     
    larssonmartin1998 likes this.