private void RecordDatum(bool immediate) { // If recording is stopped (which is it by default), loop back around next frame. if (recordingStopped) { return; } if (!immediate) // we run in the same thread as unity we can update the transformations in a synchronized way { UpdateFoveInterfaceMatrices(false); } Matrix4x4 transformMat; lock (foveInterfaceTransfo) { switch (raysCoordinateSpace) { case CoordinateSpace.World: transformMat = foveInterfaceTransfo.HMDToWorld; break; case CoordinateSpace.Local: transformMat = foveInterfaceTransfo.HMDToLocal; break; default: transformMat = Matrix4x4.identity; break; } } var leftEyeOffset = FoveManager.GetLeftEyeOffset(immediate); var rightEyeOffset = FoveManager.GetRightEyeOffset(immediate); var leftEyeVector = FoveManager.GetLeftEyeVector(immediate); var rightEyeVector = FoveManager.GetRightEyeVector(immediate); Ray leftRay, rightRay; Utils.CalculateGazeRays(ref transformMat, ref leftEyeVector, ref rightEyeVector, ref leftEyeOffset, ref rightEyeOffset, out leftRay, out rightRay); // If you add new fields, be sure to write them here. var datum = new RecordingDatum { frameTime = stopwatch.Elapsed.TotalSeconds, leftGaze = leftRay, rightGaze = rightRay, }; dataSlice.Add(datum); if (dataSlice.Count >= writeAtDataCount) { // Make sure we have exclusive access by locking the mutex, but only wait for up to 30 milliseconds. if (!writingDataMutex.WaitOne(30)) { // If we got here, it means that we couldn't acquire exclusive access within the specified time // limit. Likely this means an error happened, but it could also mean that more data was being // written than it took to gather another set of data -- in which case you may need to extend the // timeout duration, though that will cause a noticeable frame skip in your application. // For now, the best thing we can do is continue the loop and try writing data again next frame. long excess = dataSlice.Count - writeAtDataCount; if (excess > 1) { Debug.LogError("Data slice is " + excess + " entries over where it should be; this is" + "indicative of a major performance concern in the data recording and writing" + "process."); } return; } CheckForNullDataToWrite(); // Move our current slice over to dataToWrite, and then create a new slice. dataToWrite = dataSlice; dataSlice = new List <RecordingDatum>((int)(writeAtDataCount + 1)); // Release our claim on the mutex. writingDataMutex.ReleaseMutex(); if (!threadWaitHandle.Set()) { Debug.LogError("Error setting the event to wake up the file writer thread"); } } }