Programmatic Recording Quick Start
This tutorial requires Recolude.Core to be installed in the project.
For an overview of what a recording can contain, reference the Anatomy of a Recording guide. Generally you will want to make use of the Recorder class to capture what's going on within an application to easily construct Recordings. Constructing a recorder is as simple as
var recorder = new Recorder();
Similar to recordings, the recorder itself is hierarchical in nature. Therefor the API has been designed to allow developers to easily construct hierarchies to fit their needs. The code:
var root = new Recorder();
var childA = root.Register("a", "Child A");
var childB = root.Register("b", "Child B");
var childC = childA.Register("c", "Child C");
Builds out a recorder hierarchy which corresponds to the image below:
Tracking Game Objects
To track a game object, you just pass it to the root Recorder's Register function. By default, registering a game object to be recorded will automatically use the Basic Subject Recorder Strategy for observing changes of the game object. This strategy automatically begins observing the game objects position, rotation, and lifecycle events.
To actually begin a recording, you must start the recorder by calling Start. Calling Start
is a recursive operation in which it will traverse all registered sub recorders and call their respective Start
methods as well. To create a recording you need to call Finish (also a recursive operation) which will return a Recording.
Custom Events
Recorders have a utility method for capturing custom events without ever having to explicitly create a capture collection. If the utility method is never used while the recorder is running, then the resulting recording will not include a custom event capture collection. Custom Event collections have been made a first class citizen to act as a catch-all for capturing application specific data. A custom event is just the combination of a name and a metadata block. For example, capturing the data from an OnCollision event might look like:
void OnCollisionEnter(Collision collision)
{
var collisionMetadata = new Metadata();
collisionMetadata["impulse"] = new Vector3Property(collision.impulse);
collisionMetadata["collider"] = new StringProperty(collision.transform.name);
myRecorder.CaptureCustomEvent("Collision", collisionMetadata);
}
Metadata
Recorders have their own metadata blocks that get to the final Recording when Finish is called. To learn more on how to use Metadata, check out this guide. When re-using the recorder object across multiple recordings, be use to call ClearMetadata if you want to ensure each Recording get's it's own unique metadata block.
Saving a Recording
To save recordings, you'll want to use the RAPWriter. If you want to serialize custom Capture types, you'll need to implement the IEncoder.
var recording = recorder.Finish();
var filepath = $"{Application.dataPath}/demo.rap";
using (var fs = System.IO.File.Create(filepath))
using (var rapWriter = new Recolude.Core.IO.RAPWriter(fs))
{
rapWriter.Write(rec);
}
Example
using System.IO;
using UnityEngine;
using Recolude.Core.IO;
using Recolude.Core.Record;
using Recolude.Core.Properties;
///<summary>
/// This script is meant to act as a demo for creating recordings. It creates 3
/// boxes and registers them to be recorded. It then starts the root recorder.
/// The user can choose to stop the recorder by clicking the save
/// button. Clicking the save button takes the recording and saves it to assets
/// folder in the project.
///</summary>
public class RecordingExample : MonoBehaviour
{
// The recorder in charge of keeping up with all the subjects in the
//scene.
Recorder recorder;
[SerializeField]
int numberOfCubes = 3;
// Start is called before the first frame update
void Start()
{
// Create a new root recording
recorder = new Recorder();
var incrementor = 8f / (numberOfCubes - 1);
for (int i = 0; i < numberOfCubes; i++)
{
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.AddComponent<Rigidbody>();
cube.transform.position = new Vector3((i * incrementor) - 4f, 3, 0);
// Create a Child Recorder and set it to track the cube.
recorder.Register(cube);
}
// Store info about the cube drop simulation
recorder.SetMetaData("Number of Cubes", new IntProperty(numberOfCubes));
// Start the recorder so it will capture all events occuring both
// to it and the registered children recorders.
recorder.Start();
}
private void OnGUI()
{
// If the recorder is currently recording and the player clicks
// save...
if (recorder.CurrentlyRecording() && GUILayout.Button("Save"))
{
// Create a recording with all captured events up to this
// point and stop the recorder from accepting any new
// event captures.
var recording = recorder.Finish();
// Take the recording we just created and save it to the
// assets folder inside our project.
using (FileStream fs = File.Create(string.Format("{0}/demo.rap", Application.dataPath)))
using (var rapWriter = new RAPWriter(fs))
{
rapWriter.Write(recording);
}
}
}
}