The integration guide details how to save screen captures and how to log serializable data to a file. Since these two actions are performed asynchronously we will need to call the Unity Simulation APIs directly and use the image name as a joining key between images and logged data.
In this guide we will create a short simulation that runs for five seconds. The simulation will generate a screen capture and associated data point each second and then quit.
- Create a new Unity scene
- Import Unity Simulation package into Unity
- Create a C# script named DataPoint and paste the following code
using UnityEngine;
[System.Serializable]
public class DataPoint : System.Object
{
public string objectName; // Name of displaying camera
public float x; // X Rotation of game object
public float y; // Y Rotation of game object
public float z; // Z Rotation of game object
public float time; // Time of screen/data capture
public string screenCaptureName; // Name of saved image to correlate data
public DataPoint(string objectName, Quaternion rotation, float time, string screenCaptureName)
{
this.objectName = objectName;
this.x = rotation.x;
this.y = rotation.y;
this.z = rotation.z;
this.time = time;
this.screenCaptureName = screenCaptureName;
}
}- Create a C# script named
ScreenDataCaptureand paste the following code
using UnityEngine;
using Unity.AI.Simulation;
using UnityEngine.Experimental.Rendering;
using System;
public class ScreenDataCapture : MonoBehaviour
{
// Camera object in scene
public Camera _camera;
public GameObject _cube;
private int duration = 5;
private int captureInterval = 1;
private int lastCapture;
private float simElapsed;
private bool quit; // Editor use only, minimizes screen/data captures
private Unity.AI.Simulation.Logger dataLogger;
private string screenCapturePath;
private void Start()
{
Debug.Log(Application.persistentDataPath + "/" + Configuration.Instance.GetAttemptId());
screenCapturePath = DXManager.Instance.GetDirectoryFor(DataCapturePaths.ScreenCapture);
// Data logger defaults to the same run directory as ScreenCapture
dataLogger = new Unity.AI.Simulation.Logger("DataCapture");
}
private void Capture(int num)
{
string imageName = _camera.name + "_" + num;
// Define Data point object outside async call
DataPoint dataPoint = new DataPoint(_cube.name, _cube.transform.rotation, simElapsed, imageName);
// Call Screen Capture
var screen = CaptureCamera.Capture(_camera, request =>
{
string path = string.Format("{0}/{1}.jpg", screenCapturePath, imageName);
// Ensure that the width & height match the aspect ratio
// Refer https://docs.unity3d.com/Manual/GameView.html
int width = 1024;
int height = 768;
bool flipY = false;
// Convert the screen capture to a byte array
Array image = CaptureImageEncoder.Encode(
request.data.colorBuffer as Array,
width, height,
GraphicsFormat.R8G8B8A8_UNorm,
CaptureImageEncoder.ImageFormat.Jpg,
flipY);
// Write the screen capture to a file
var result = DXFile.Write(path, image);
// Wait for Async screen capture request to return and then log data point
if (result)
{
// Log data point to file
dataLogger.Log(dataPoint);
return AsyncRequest.Result.Completed;
}
return AsyncRequest.Result.Error;
});
}
private void Update()
{
// Get total time sim elapsed
simElapsed += Time.deltaTime;
// Sim has hit duration, flush all data and quit application
if (simElapsed >= duration && !quit)
{
dataLogger.Flushall();
quit = true;
Debug.Log("Quitting...");
Application.Quit();
}
// Capture Data if last time capture time was over 1 second ago
if ((int)simElapsed - lastCapture >= captureInterval && !quit)
{
Capture(lastCapture);
lastCapture = (int)simElapsed;
}
}
}- Create an empty GameObject and drag the
ScreenDataCaptureon to it and then drag and drop theMain Camerainto the_cameraslot - Add a cube to the scene and drag the cube onto the
_cubeslot in theScreenDataCapturecomponent. - Create a C# script named
CubeSpinnerand paste the following code
using UnityEngine;
public class CubeSpinner : MonoBehaviour
{
void Update()
{
transform.Rotate(0, 50 * Time.deltaTime, 50 * Time.deltaTime);
}
}- Drag and drop the
CubeSpinnerscript onto the cube game object. - Press play again to stop the scene once the
Quitting...message appears in the console. - Navigate to the
Application.persistentDataPaththat was logged to the console by theScreenDataCapturescript after pressing the play button. - Finally, locate a directory named with a random GUID with
ScreencaptureandLogsdirectories contained within to look at your data.
- The contents of the logged data in the
Logsdirectory
{"objectName":"Cube","x":0.015206203795969487,"y":0.4096302390098572,"z":0.4170513153076172,"time":1.013169527053833,"screenCaptureName":"Main Camera_0"}
{"objectName":"Cube","x":0.011952600441873074,"y":0.6593078374862671,"z":0.6751770973205566,"time":2.000636339187622,"screenCaptureName":"Main Camera_1"}
{"objectName":"Cube","x":0.004186167847365141,"y":0.6690274477005005,"z":0.6876687407493591,"time":3.0099940299987795,"screenCaptureName":"Main Camera_2"}
{"objectName":"Cube","x":-0.005022712983191013,"y":0.43267545104026797,"z":0.44719454646110537,"time":4.004084587097168,"screenCaptureName":"Main Camera_3"}Main Camera_0Image form theScreenCapturesdirectory
- Using the
screenCaptureNamevalue in each logged DataPoint we can determine that the cube rotation values in the above image are(0.015206203795969487, 0.4096302390098572, 0.4170513153076172)and they were captured at1.013169527053833seconds during the simulation.
