GIF Recording

There are two components for GIFs inside SA.GIF namespace - the Recorder and the Player. The first one used for GIFs recording  and the second one for GIFs displaying accordingly. Let's start with GIFs recording at first and then move to GIFs displaying.

Recording

First, start with creating the SA.GIF.Recorder object and subscribe for all the event callback of it

SA.GIF.Recorder recorder;

void Start () {
	recorder = new SA.GIF.Recorder ();
	recorder.OnPreProcessingDone += Recorder_OnPreProcessingDone;
	recorder.OnFileSaveProgress += Recorder_OnFileSaveProgress;
	recorder.OnFileSaved += Recorder_OnFileSaved;
}

private void Recorder_OnFileSaved (int id, string path) { }
private void Recorder_OnFileSaveProgress (int id, float progress) { }
private void Recorder_OnPreProcessingDone () { }

The example code above has the Recorder creation in the Start method, but that may be any other method you want. Good approach is to subscribe to all event callbacks right after Recorder constructor. In this example, the default constructor demonstrated, but the Recorder class has an additional constructor with the Camera object as a parameter. Every Recorder  should have the Camera component to be recorded from. In a case of the parameterless constructor, the Recorder will be created for the Main Camera in your scene. Otherwise, you have to provide the camera while creating the Recorder object.

Creating the Recorder  with the appropriate camera looks following

Camera recordCamera;
SA.GIF.Recorder recorder;

void Start () {
	recorder = new SA.GIF.Recorder (recordCamera);
	//Event subscription goes following
}

The options for newly created Recorder will be from SocialGif Settings. If you want to change recorder options, use Setup method as shown below

SA.GIF.Recorder recorder;

void Start () {
	recorder = new SA.GIF.Recorder (recordCamera);
	recorder.Setup (true, //autoAspect
                    400,  //width
                    400,  //height
                    30,   //fps
                    5.0f, //bufferSize
                    1,    //repeat
                    15);  //quality
}

Setup method definition is following

public void Setup(bool autoAspect, int width, int height, int fps, float bufferSize, int repeat, int quality)
  • autoAspect - automatically compute height from the current camera aspect ratio.
  • width - width of the GIF in pixels.
  • height - height of the GIF in pixels.
  • fps - recording FPS.
  • bufferSize - maximum amount of seconds to record to memory.
  • repeat - GIF recording repeat count. -1  no repeat, 0  infinite, >0  repeat count.
  • quality - quality of color quantization (conversion of images to the maximum 256 colors allowed by the GIF specification). Lower values (minimum = 1) produce better colors, but slow processing significantly. Higher values will speed up the quantization pass at the cost of lower image quality (maximum = 100).

 

More detailed description of Recorder event callbacks is following:

  • Action OnPreProcessingDone - Called when the pre-processing step has finished.
  • Action<int, float> OnFileSaveProgress - Called by each worker thread every time a frame is processed during the save process. The first parameter holds the worker ID and the second one a value in a range [0;1] for the actual progress.
  • Action<int, string> OnFileSaved - Called once a gif file has been saved. The first parameter will hold the worker ID and the second one the absolute file path.

Important: Don't forget to unsubscribe from Recorder events and flush the memory by calling FlushMemory method. FlushMemory is the void method that clears all saved frames from memory and starts fresh. The best places to do this are OnDestroy method of your MonoBehavior script or in OnFileSaved callback.

// #1 Unsubscribe and memory flushing in OnDestroy method of your MonoBehavior
void OnDestroy() {
	recorder.OnPreProcessingDone -= Recorder_OnPreProcessingDone;
	recorder.OnFileSaveProgress -= Recorder_OnFileSaveProgress;
	recorder.OnFileSaved -= Recorder_OnFileSaved;

	recorder.FlushMemory ();
}

// #2 Unsubscribe and memory flushing in OnFileSaved callback
private void Recorder_OnFileSaved (int id, string path) {
	//Sharing code goes here

	recorder.OnPreProcessingDone -= Recorder_OnPreProcessingDone;
	recorder.OnFileSaveProgress -= Recorder_OnFileSaveProgress;
	recorder.OnFileSaved -= Recorder_OnFileSaved;

	recorder.FlushMemory ();
}

Now, after the creation of Recorder object, subscribing (and unsubscribing!) for all the event callback we are ready to go with the actual recording!

There are three methods for controlling GIF recording process:

  • public void Record() - Starts or resumes recording. You can't resume while it's pre-processing data to be saved.
  • public void Pause() - Pauses recording. The recording can be resumed after it has been paused.
  • public void Stop() - Stops recording. The recording can NOT be resumed after it has been stopped.

 

At first, you need some basic setup in your game scene for it. E.g. I have a bike-racing game and I want to record the GIF of the player finish. Of course, some basic setup will be required to implement this logic. The best way, in this case, is to create the trigger collider a little before the finish. When the player will enter this trigger you have to make the Recorder.Record() method call to instantly start GIF recording. The second trigger collider needed far behind the finish. You will stop the GIF recording when the player will enter this trigger. Make a Recorder.Stop() method call to stop recording. The Pause/Record methods may be called as many times as you want, but it will not take any effect after you called Stop.

Important:  Let's clarify GIF recording buffer size value. That's the maximum amount of seconds to record to memory. If you set 5 seconds for buffer size but didn't stop the recording when the 5 seconds were out, that will not cause any kind of issues. But you have to take into account that recording will not stop until Pause or Stop method calls and the older GIFs frames will be removed and the new ones will be added to the buffer. Honestly, the GIF frames recording has frames queue under the hood. So, please, keep this in your mind while recording the GIF from your gameplay.

Please, take a look at GIFs recording methods calls from the code

public void OnStartTheRecordClick() {
		//Instantly starts the GIF recording
		recorder.Record ();
	}

	public void OnPauseRecordClick() {
		//Pause the recording process. The recording may be resumed
		recorder.Pause ();
	}

	public void OnStopRecordClick() {
		//Stop the recording. The recording can NOT be resumed after it has been stopped
		recorder.Stop ();

		//Saves the stored frames to a gif file. You can call this method in any place in your
        // code. It's called right after Stop method just for this particular example
		recorder.Save ();
	}

After you performed GIFs recording and made Stop method call, you are ready to go with GIF saving. That's not required to save the GIF files locally before displaying them. Just record it and show to the player in you in-game UI. But if you are going to share the GIF, you definitely have to save it.

If you don't want to save the GIF at the beginning, you may prompt the player about it and save the GIF right after the positive answer. There is overloaded Save method of the Recorder class - with and without string GIF file name.

public void Save()

Saves the stored frames to a gif file. The filename will automatically be generated. The recording will be paused and won't resume automatically. You can use the OnPreProcessingDone callback to be notified when the pre-processing step has finished.

public void Save(string filename)

Saves the stored frames to a gif file. If the filename is null or empty, a unique one will be generated. You don't need to add the .gif extension to the name. The recording will be paused and won't resume automatically. You can use the OnPreProcessingDone callback to be notified when the pre-processing step has finished.

  • filename - the filename for the GIF file without extension.

You will receive all the events mentioned above about pre-processing done, file saving process and file saving finished. The last event you will receive is OnFileSaved event callback. It indicates that all the saving process have been done and you are ready to GIF sharing (or displaying in your in-game UI). And the absolute GIF file path will be returned with this event callback.

Displaying

Now, when you are able to record your gameplay as a GIF with any camera in your game scene you are ready to move to GIF displaying part. For this purpose the SA.GIF.Player exists. Let's move to GIFs displaying features.

That's pretty simple to handle with SA.GIF.Player object to make your GIF displayed in the Unity UI Image. All you need is to create SA.GIF.Player object with SA.GIF.Recorder and UnityEngine.UI.Image provided and call Player.Play() method.

SA.GIF.Player gifPlayer = new SA.GIF.Player (recorder, gifImage);
gifPlayer.Play ();

The constructor of SA.GIF.Player looks like following

public Player(Recorder recorder, Image destination)
  • recorder - the SA.GIF.Recorder object. That's the exactly that object which you used for GIF recording.
  • destination - the UnityEngine.UI.Image object on which the GIF frames sequence will be displayed.

That's all with GIF displaying as a part of your UI. As you can see, it's super-simple to work with GIFs displaying. You don't need to call any kind of additional methods of SA.GIF.Player object, just create it with all the resources provided and call the Play method call.

All the samples you can find in Assets/Plugins/StansAssets/Modules/SocialGif/xExamples/Demo scene. We use some free assets from Unity Asset Store from our demonstration, so, this sample requires minimum Unity v5.4.0f3 for a test. In older Unity versions you will just get an empty scene.

Finally, we are done with GIFs recording/displaying! It's time to move to GIFs sharing features guide.