Search Unity

How to avoid invalidating NativeArrays?

Discussion in 'Entity Component System' started by HeyZoos, Nov 17, 2018.

  1. HeyZoos

    HeyZoos

    Joined:
    Jul 31, 2016
    Posts:
    50
    The NativeArray hasn't been altered anywhere in the OnUpdate method, I push changes to after the update using the provided barrier system PostUpdateCommands.

    This code still produces a "NativeArray has been deallocated" exception, however. What am I doing wrong here and what are some good rules of thumb or mental models to avoid it?

    Code (CSharp):
    1. using Unity.Entities;
    2. using UnityEngine;
    3.  
    4. public class ShootingSystem : ComponentSystem
    5. {
    6.     public ComponentGroup componentGroup;
    7.  
    8.     protected override void OnStartRunning()
    9.     {
    10.         componentGroup = GetComponentGroup(
    11.             ComponentType.Create<ProjectileSpawnComponent>(),
    12.             ComponentType.Create<Transform>()
    13.         );
    14.     }
    15.  
    16.     protected override void OnUpdate()
    17.     {
    18.         var delta = Time.fixedDeltaTime;
    19.         var entities = componentGroup.GetEntityArray();
    20.         var transforms = componentGroup.GetComponentArray<Transform>();
    21.         var spawners = componentGroup.GetComponentDataArray<ProjectileSpawnComponent>();
    22.  
    23.         for (int i = 0; i < spawners.Length; i++)
    24.         {
    25.             var spawner = spawners[i];
    26.             var transform = transforms[i];
    27.  
    28.             if (spawner.cooldown <= 0f)
    29.             {
    30.                 // Reset the spawner's cooldown.
    31.                 spawner.cooldown = spawner.firerate;
    32.  
    33.                 // Spawn a bullet and send it flying!
    34.                 var prototype = GameObject.Find("Prototypes").GetComponent<Prototypes>().Bullet;
    35.                 var bullet = GameObject.Instantiate(prototype);
    36.                 bullet.GetComponent<Transform>().position = transform.position;
    37.                 bullet.GetComponent<Rigidbody>().velocity += transform.forward * 50;
    38.             }
    39.  
    40.             // Descrement the cooldown and save all our changes to the spawner.
    41.             spawner.cooldown -= delta;
    42.  
    43.             // Queue up changes after update so we don't invalidate our native arrays.
    44.             PostUpdateCommands.SetComponent<ProjectileSpawnComponent>(entities[i], spawner);
    45.         }
    46.     }
    47. }
     
  2. Piefayth

    Piefayth

    Joined:
    Feb 7, 2017
    Posts:
    61
    Just a guess based on issues I was having yesterday, but I think your reference to entities is no longer valid once PostUpdateCommands actually runs the commands you are queueing. Like, it's pointing to an index in an array that' gets invalidated before it's used. I just keep a reference to the Entity that I actually have ownership of.

    Code (CSharp):
    1. Entity e = entities[i]
    2. PostUpdateCommands.SetComponent<Data>(e, data);
     
    Last edited: Nov 17, 2018
  3. HeyZoos

    HeyZoos

    Joined:
    Jul 31, 2016
    Posts:
    50
    Whoa yep that fixed it! I'm pretty confused as to why, however. Don't they both point to the same location in memory?