Search Unity

Question NativeArray'1[T].CheckElementReadAccess leading to null reference error

Discussion in 'Scripting' started by kirov099, Sep 16, 2021.

  1. kirov099

    kirov099

    Joined:
    Jun 28, 2017
    Posts:
    3
    Hello. I've been playing around in Unity as a hobby for a while, though I haven't really interacted here before. I decided to try out the job system for the first time, with hopes of improving my terrain generation code. Unfortunately, I've run into a problem that I'm having some trouble resolving. Normally, I'd be able to google it and find some answers, but that doesn't seem to be yielding many results.

    Here's the error that I'm getting:

    NullReferenceException: Object reference not set to an instance of an object
    Unity.Collections.NativeArray`1[T].CheckElementReadAccess (System.Int32 index) (at <88f69663e9a64d00b2091dd8dfd4d38f>:0)
    Unity.Collections.NativeArray`1[T].get_Item (System.Int32 index) (at <88f69663e9a64d00b2091dd8dfd4d38f>:0)
    TerrainHandler.GetTerrainData (TerrainHandler+JobHandler handler) (at Assets/Scripts/Terrain/TerrainHandler.cs:199)
    TerrainHandler.FixedUpdate () (at Assets/Scripts/Terrain/TerrainHandler.cs:126)

    And here's the relevant function from my code. Line 199 corresponds to 19 near the bottom, inside the doubly nested for loop. Note that the first two debug statements print out in the console, but the second two do not.

    Code (CSharp):
    1.  
    2. float[,] GetTerrainData( JobHandler handler ) {
    3.  
    4.         Debug.Log( "GetTerrainData" );
    5.  
    6.         handler.handle.Complete();
    7.  
    8.         handler.finalJobResult = new float[TerrainGeneration.GetTerrainWidth(), TerrainGeneration.GetTerrainHeight()];
    9.         Debug.Log( "Job completed, finalJobResult initialized");
    10.         if ( handler.finalJobResult == null ) {
    11.             Debug.Log( "finalJobResult is null" );
    12.         }
    13.         if ( handler.jobResult == null ) {
    14.             Debug.Log( "jobResult is null" );
    15.         }
    16.         for ( int i = 0; i < TerrainGeneration.GetTerrainWidth(); i++ ) {
    17.             for ( int j = 0; j < TerrainGeneration.GetTerrainHeight(); j++ ) {
    18.  
    19.                 handler.finalJobResult[i,j] = handler.jobResult[ i * TerrainGeneration.GetTerrainWidth() + j ];
    20.             }
    21.         }
    22.  
    23.         handler.jobResult.Dispose();
    24.  
    25.         return handler.finalJobResult;
    26.     }
    27.  
    A JobHandler is a struct which contains a JobHandle and a few other variables to help me keep track of things. As I said, I'm new to the job system, so I'm sure there's something I'm missing. Or perhaps I'm just overlooking something even simpler and will look silly once someone points it out, as seems to happen to me a lot. But as far as I can tell, everything seems to be order. The error log seems to be pointing to some internal function that I don't have access to. Any help would be greatly appreciated. If there's any other code which I should be showing, I'd be happy to share.
     
  2. kirov099

    kirov099

    Joined:
    Jun 28, 2017
    Posts:
    3
    Okay, I figured out what the issue was, and it was embarrasingly simple, which is exactly what I was afraid would happen if I posted this. Turns out I declared my job in a function, so it was disappearing after that function call completed. I've since fixed that, but now I've run into another problem. Since I've already put this thread out there, I figured I'd update and ask for help again.

    Error:
    InvalidOperationException: The previously scheduled job TerrainGeneration:ValueNoiseJob writes to the Unity.Collections.NativeArray`1[System.Single] ValueNoiseJob.result. You must call JobHandle.Complete() on the job TerrainGeneration:ValueNoiseJob, before you can read from the Unity.Collections.NativeArray`1[System.Single] safely.
    Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckReadAndThrowNoEarlyOut (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle handle) (at <ad3eaa0878d94cbe8e45f9c494d71647>:0)
    Unity.Collections.NativeArray`1[T].CheckElementReadAccess (System.Int32 index) (at <ad3eaa0878d94cbe8e45f9c494d71647>:0)
    Unity.Collections.NativeArray`1[T].get_Item (System.Int32 index) (at <ad3eaa0878d94cbe8e45f9c494d71647>:0)
    TerrainHandler.GetTerrainData (TerrainHandler+JobHandler handler) (at Assets/Scripts/Terrain/TerrainHandler.cs:200)
    TerrainHandler.Start () (at Assets/Scripts/Terrain/TerrainHandler.cs:55)

    Relevant Functions:
    Code (CSharp):
    1.     bool StartTerrainJob( JobHandler handler, int chunkx, int chunky ) {
    2.  
    3.         handler.valueNoiseJob = new TerrainGeneration.ValueNoiseJob();
    4.         handler.valueNoiseJob.chunkx = chunkx;
    5.         handler.valueNoiseJob.chunky = chunky;
    6.         handler.valueNoiseJob.result = handler.jobResult;
    7.  
    8.         handler.handle = handler.valueNoiseJob.Schedule();
    9.  
    10.         return true;
    11.     }
    12.  
    13.     float[,] GetTerrainData( JobHandler handler ) {
    14.  
    15.         handler.handle.Complete();
    16.  
    17.         for ( int i = 0; i < TerrainGeneration.GetTerrainWidth(); i++ ) {
    18.             for ( int j = 0; j < TerrainGeneration.GetTerrainHeight(); j++ ) {
    19.  
    20.                 handler.finalJobResult[i,j] = handler.jobResult[ i * TerrainGeneration.GetTerrainWidth() + j ];
    21.             }
    22.         }
    23.  
    24.         handler.jobResult.Dispose();
    25.  
    26.         return handler.finalJobResult;
    27.     }
    Line 200 corresponds to 20 in the posted code. I'm calling Complete() 5 lines above that, so I don't understand why the error is being raised.