I am trying to queue items up in one script, and dequeue them while launching on separate threads in another script. Everytime my queue is over a set number, it should launch a bunch of separate jobs. I don't really care about waiting to see if they complete as they're bursting messages over UDP. I've put together a small sample of what I'm trying to do, but I'm not successfully passing the information from one script into another. I regularly get errors on object references not set to an instance of an object. I'd greatly appreciate some input! Code (CSharp): using System.Collections; using System.Collections.Generic; using UnityEngine; using Unity.Collections; using Unity.Jobs; using UnityEngine.Profiling; using Unity.Entities; public class test_creator : MonoBehaviour { public NativeQueue<float> myQueue = new NativeQueue<float>(Allocator.Persistent); public NativeArray<float> myArray; void FixedUpdate() { // Populate data myQueue.Enqueue(1.0f); Debug.Log("creator Queue size " + myQueue.Count); } } Code (CSharp): using System.Collections; using System.Collections.Generic; using UnityEngine; using Unity.Collections; using Unity.Jobs; using UnityEngine.Profiling; using Unity.Entities; public class test_doer : MonoBehaviour { [HideInInspector] public test_creator thing; public NativeQueue<float> myQueue = new NativeQueue<float>(Allocator.Persistent); // Start is called before the first frame update void Start() { } public struct SerializeJob : IJob { public NativeArray<float> myArray; public void Execute() { // serialize data Debug.Log("myArray0" + myArray[0]); } } // Update is called once per frame void Update() { myQueue = thing.myQueue; while (myQueue.Count > 2) { Debug.Log("Queue count " + myQueue.Count); var myArray = new NativeArray<float>(2, Allocator.Temp); myArray[0] = myQueue.Dequeue(); myArray[1] = myQueue.Dequeue(); // launch paralell job SerializeJob jobData = new SerializeJob(); jobData.myArray = myArray; // Schedule the job JobHandle handle = jobData.Schedule(); // Wait for th ejob to complete handle.Complete(); jobData.myArray.Dispose(); myArray.Dispose(); } } }
Null Reference exceptions should be simple to track down. What's null in your code? Maybe you need to be initializing something in Awake?
I don't understand NativeQueue's well enough to figure it out. I think Code (CSharp): thing.myQueue is null.
Well, it should tell you the line number of the NRE, for starters, in the error. And you should be able to just step through the code in the debugger until you discover what's null. Based on your earlier code, nothing is setting "thing" to a value. So, accessing any property off "thing" would give you an NRE. Or do you have some other code that sets "thing" to a value? Anyway, attach the debugger and step through the code.
Are you really enqueuing inside the main thread, or are you enqueueing from another thread? You may not realize that you are enqueueing from another thread. A common situation of receive null pointer exceptions in queueing code is using a non-thread-safe data structure. It should be clear that the C# job system is not thread-safe in the conventional sense of the term. This code omits too many of the details to really identify the issue. Try to not use the C# job system to solve this problem. If you are enqueuing data from e.g. a network thread, use a true (not off-the-Internet gist that people do) ConcurrentQueue from .Net 4.0 or later, and dequeue from it in an Update on the main thread.
I have data that I'm generating in Unity. I want to enqueue data off the main thread. I don't particularly care about how it gets dequeued. Using a concurrent method is probably best for dequeueing. If there's a way to trigger an "event" of passing X number of items, that would work as well, instead of checking every update. Current errors: A Native Collection has not been disposed, resulting in a memory leak. It was allocated at ...\Test_creator.cs:11. NullReferenceException: Object reference not set to an instance of an object. test_doer.Update() (at Assets/Scripts/test/test_doer.cs:30)[/code] test_creator.cs: Code (CSharp): using System.Collections; using System.Collections.Generic; using UnityEngine; using Unity.Collections; using Unity.Jobs; using UnityEngine.Profiling; using Unity.Entities; public class test_creator : MonoBehaviour { public NativeQueue<float> myQueue = new NativeQueue<float>(Allocator.Persistent); //public NativeArray<float> myArray; void FixedUpdate() { // Populate data myQueue.Enqueue(1.0f); Debug.Log("creator Queue size " + myQueue.Count); } private void OnDestroy() { myQueue.Dispose(); } } test_doer.cs Code (CSharp): using System.Collections; using System.Collections.Generic; using UnityEngine; using Unity.Collections; using Unity.Jobs; using UnityEngine.Profiling; using Unity.Entities; public class test_doer : MonoBehaviour { [HideInInspector] public test_creator thing; //public NativeQueue<float> myQueue;// = thing.myQueue; //new NativeQueue<float>(Allocator.Persistent); public struct SerializeJob : IJob { public NativeArray<float> myArray; public void Execute() { // serialize data Debug.Log("myArray0" + myArray[0]); } } // Update is called once per frame void Update() { //myQueue = thing.myQueue; while (thing.myQueue.Count > 2) { Debug.Log("Queue count " + thing.myQueue.Count); var myArray = new NativeArray<float>(2, Allocator.Temp); myArray[0] = thing.myQueue.Dequeue(); myArray[1] = thing.myQueue.Dequeue(); // launch paralell job SerializeJob jobData = new SerializeJob(); jobData.myArray = myArray; // Schedule the job JobHandle handle = jobData.Schedule(); // Wait for th ejob to complete handle.Complete(); jobData.myArray.Dispose(); myArray.Dispose(); } } }
First, where are you referencing test_creator in test_doer? The reference has a [HideInInspector] and no code to set the parameter. Second, avoid initialising Native Containers on declaration. It'll cause problems on prefabs. Move the declaration to Awake. Third, NativeQueue doesn't support parallel dequeue, only enqueue. []'s
The following code seems to work for anyone else that might come across a similar issue. I moved the variable definition to Awake() per elcionap's suggestions. By making the variable static, I'm able to reference it from the script's name instead. test_creator.cs Code (CSharp): using System.Collections; using System.Collections.Generic; using UnityEngine; using Unity.Collections; using Unity.Jobs; using UnityEngine.Profiling; using Unity.Entities; public class test_creator : MonoBehaviour { public static NativeQueue<float> myQueue; void Awake() { myQueue = new NativeQueue<float>(Allocator.Persistent); } void FixedUpdate() { // Populate data myQueue.Enqueue(1.0f); Debug.Log("creator Queue size " + myQueue.Count); } private void OnDestroy() { myQueue.Dispose(); } } test_doer.cs Code (CSharp): using System.Collections; using System.Collections.Generic; using UnityEngine; using Unity.Collections; using Unity.Jobs; using UnityEngine.Profiling; using Unity.Entities; public class test_doer : MonoBehaviour { public struct SerializeJob : IJob { public NativeArray<float> myArray; public void Execute() { // serialize data Debug.Log("myArray0" + myArray[0]); } } // Update is called once per frame void Update() { while (test_creator.myQueue.Count >= 2) { Debug.Log("Queue count " + test_creator.myQueue.Count); var myArray = new NativeArray<float>(2, Allocator.TempJob); myArray[0] = test_creator.myQueue.Dequeue(); myArray[1] = test_creator.myQueue.Dequeue(); // launch paralell job SerializeJob jobData = new SerializeJob(); jobData.myArray = myArray; // Schedule the job JobHandle handle = jobData.Schedule(); // Wait for the job to complete handle.Complete(); jobData.myArray.Dispose(); } } }