Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
## [2.2.0-preview.4] - 2020-04-08
### Public API and bugfixes
- Added public api's to allow loading previously saved recorder lists.
- Fixed bug where the first few frames after going in play-mode were not recorded.
- Fixed a bug where the texture sampling recorder that did not correctly support the physical cameras.
- Fixed an issue when starting a record session from scripts.
- Fixed movie recoder's default framerate value being not set in the API. Default value is now set at 30 FPS.
  • Loading branch information
Unity Technologies committed Apr 7, 2020
1 parent e395752 commit ed22282
Show file tree
Hide file tree
Showing 34 changed files with 377 additions and 146 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ All notable changes to this package will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [2.2.0-preview.4] - 2020-04-08
### Public API and bugfixes
- Added public api's to allow loading previously saved recorder lists.
- Fixed bug where the first few frames after going in play-mode were not recorded.
- Fixed a bug where the texture sampling recorder that did not correctly support the physical cameras.
- Fixed an issue when starting a record session from scripts.
- Fixed movie recoder's default framerate value being not set in the API. Default value is now set at 30 FPS.

## [2.1.0-preview.1] - 2019-12-17
### Public API and HDR recording
- Added public APIs to be able to implement custom recorders.
Expand Down
Binary file modified Documentation~/Images/RecorderWindow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions Documentation~/InclCaptureOptionsGameView.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
These options appear when you set **Capture** to **Game View**.

>[!NOTE]
>If you are using more than one Recorder to capture Game View, they must all use the same resolution settings.
>* If you have multiple Game Views in your project, the Recorder captures only the last one you selected in the Editor.
>* If you are using more than one Recorder to capture Game View, they must all use the same resolution settings.
![](Images/CaptureOptionsGameView.png)

Expand All @@ -15,4 +16,4 @@ These options appear when you set **Capture** to **Game View**.
| | _[PRESET RESOLUTIONS]_ | Choose from several standard video resolutions such as 1080p and 4K. |
| | Custom | Uses custom width and height values that you supply. |
| **Aspect Ratio** ||These options appear when you set **Output Resolution** to **Custom**.|
| | W/H | Control the recording's width and height.<br/><br/> |
| | W/H | Control the recording's width and height.<br/><br/> |
6 changes: 0 additions & 6 deletions Documentation~/RecorderGif.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ This page covers properties specific to GIF Animation Recorders. To fully config
|Property:||Function:|
|:---|:---|:-|
| **Capture** ||Specifies the input for the recording.|
|| Game View |Records frames rendered in the Game View.<br/><br/>Selecting this option displays the [Game View capture properties](#GameView). |
|| Targeted Camera |Records frames captured by a specific Camera, even if the Game View does not use that Camera.<br/><br/>Selecting this option displays the [Targeted Camera capture properties](#TargetedCamera).|
|| 360 View |Records a 360-degree video.<br/><br/>Selecting this option displays the [360 View capture properties](#360View).|
|| Render Texture Asset |Records frames rendered in a Render Texture.<br/><br/>Selecting this option displays the [Render Texture Asset capture properties](#RenderTextureAsset).|
|| Texture Sampling |Supersamples the **Source** camera during the capture to generate anti-aliased images in the recording. Use this capture method when the **Rendering Resolution** has the same or higher resolution than the **Output Resolution**. <br/><br/>Selecting this option displays the [Texture Sampling capture properties](#TextureSampling).|
| **Encoding** ||Properties for controlling the quality and size of the .gif output.|
Expand All @@ -29,7 +27,3 @@ This page covers properties specific to GIF Animation Recorders. To fully config
[!include[<title>](InclCaptureOptionsRenderTextureAsset.md)]

[!include[<title>](InclCaptureOptionsTextureSampling.md)]




7 changes: 3 additions & 4 deletions Documentation~/RecorderManage.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ Right click the Recorder you want to delete and choose **Delete** from the conte

Or

Select the Recorder you want to delete and use the **Ctrl/Cmd + Delete** shortcut.
Select the Recorder you want to delete and:
* On Windows or Linux, press **Delete**, or
* On Mac, use the **Cmd + Delete** shortcut.

<a name="ManageRecorderLists"></a>
## Managing Recorder lists
Expand Down Expand Up @@ -65,6 +67,3 @@ Use the Preset icon ![](Images/IconPreset.png) in the Recorder Properties pane t
This is useful for creating predefined Recorders that you can reuse in different [Recorder Lists](#ManageRecorderLists).

For information about saving and loading Presets, see the [Presets](https://docs.unity3d.com/Manual/Presets.html) section in the Unity Manual.



4 changes: 1 addition & 3 deletions Documentation~/RecorderProperties.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Setting Recorder properties

To configure a Recorder, set its properties in the [Recorder window](RecorderWindow.md) or, if you're recording from a Timeline Track, in the [Recorder Clip Inspector](RecordingTimelineTrack,md).
To configure a Recorder, set its properties in the [Recorder window](RecorderWindow.md) or, if you're recording from a Timeline Track, in the [Recorder Clip Inspector](RecordingTimelineTrack.md).

From there, you can set the following types of properties:

Expand Down Expand Up @@ -44,5 +44,3 @@ These properties define file output options for any type of Recorder.
| | _[PATH]_ | Displays the full output path, as set in the **File Name** and **Path** properties. |
| | File Browser button <br/>![](Images/RecorderReveal.png) | Opens your operating system's file browser to the current path. |
|**Take Number** || A value that the Recorder uses to number recordings. It increases by one after each recording. <br/><br/>You can use the **<Take>** wildcard to append current **Take** value to the **File Name**. |


7 changes: 2 additions & 5 deletions Documentation~/RecordingPlayMode.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,10 @@ Use the **Frame Rate** properties to specify how to constrain the frame rate dur
| **Record Mode** ||Specifies the frames or time interval to record.|
||_Manual_ |Start and stop recording when you manually click **Start Recording** and **Stop Recording**, respectively.|
|| _Single Frame_ |Record a single frame. Use the **Frame Number** property to specify this frame.|
|| _Frame Interval_ |Record a set of consecutive frames during Play mode. Use the **First Frame** and **Last Frame** properties to specify when to start and stop.|
|| _Frame Interval_ |Record a set of consecutive frames during Play mode. Use the **Start** and **End** properties to specify when to start and stop.|
|| _Time Interval_ |Record a specific duration, in seconds, during Play mode. Use the **Start** and **End** properties to specify when to start and stop.|
| **Frame Number** ||Specifies the number of the frame to capture when in **Single Frame** mode.|
| **First Frame**/ <br/> **Last Frame** ||Specifies the range of frames to capture when in **Frame Interval** mode.|
| **Start**/ <br/> **End** ||Specifies the time, in seconds, to start and stop recording.|
| **Start**/ <br/> **End** ||• When in **Frame Interval** mode, specifies the range of frames to capture.<br/>• When in **Time Interval** mode, specifies the time, in seconds, to start and stop recording.|

### Frame Rate properties

Expand Down Expand Up @@ -76,5 +75,3 @@ When a recording stops the Editor remains in Play mode unless:
- Use the **F10**/**fn+F10** shortcut.
- Close the Recorder window.
- Exit Play mode.


6 changes: 3 additions & 3 deletions Documentation~/RecordingTimelineTrack.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ To set up a recording session in a Timeline instance:

## Editing Recorder Clip properties

Recorder Clip properties are the same as regular [Recorder properties](RecorderSetup.md), but you set them from the Recorder Clip inspector rather than the Recorder window.
Recorder Clip properties are the same as regular [Recorder properties](RecorderProperties.md), but you set them from the Recorder Clip inspector rather than the Recorder window.

![Adding a Recorder Track in Timeline.](Images/RecorderClipProperties.png)

|||
|-|-|
|![](Images/Label-A.png) | Choose the type of Recorder you want the Recorder Clip to use. |
|![](Images/Label-B.png) | Load any existing [Recorder Preset](RecorderManage.md#RecorderPreset), or save the current Recorder Clip settings as a Preset. |
|![](Images/Label-C.png) | Set the Recorder Clip properties. These vary according to the **Selected Recorder** setting. You set them the same way you set regular [Recorder properties](RecorderSetup.md). |
|![](Images/Label-C.png) | Set the Recorder Clip properties. These vary according to the **Selected Recorder** setting. You set them the same way you set regular [Recorder properties](RecorderProperties.md). |

>[!NOTE]
> Unity stores the **Recorder Clip** properties in the Timeline Track. They do not affect properties you set in the Recorder window.
Expand All @@ -47,4 +47,4 @@ The Recorder Clip Inspector also includes a subset of the [recording controls](R
|-|-|
|![](Images/Label-A.png) | The Recorder Clip's **Clip Timing** properties control the recording's **Start**, **End**, and **Duration**. |
|![](Images/Label-B.png) | The **Frame Rate > Playback** property is locked to **Constant** mode, because Timeline plays back at a constant frame rate. |
|![](Images/Label-C.png) | The Recorder Clip inherits its **Frame Rate > Target** setting from the Timeline’s **Frame Rate** setting. |
|![](Images/Label-C.png) | The Recorder Clip inherits its **Frame Rate > Target** setting from the Timeline’s **Frame Rate** setting. |
4 changes: 2 additions & 2 deletions Editor/Sources/BaseRenderTextureInput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ public abstract class BaseRenderTextureInput : RecorderInput
/// <summary>
/// Stores the output image width.
/// </summary>
protected internal int OutputWidth { get; protected set; }
public int OutputWidth { get; protected set; }
/// <summary>
/// Stores the output image height.
/// </summary>
protected internal int OutputHeight { get; protected set; }
public int OutputHeight { get; protected set; }

/// <summary>
/// Releases all resources allocated by this class instance.
Expand Down
11 changes: 8 additions & 3 deletions Editor/Sources/BaseTextureRecorder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ public abstract class BaseTextureRecorder<T> : GenericRecorder<T> where T : Reco
{
int m_OngoingAsyncGPURequestsCount;
bool m_DelayedEncoderDispose;
bool m_UseAsyncGPUReadback;

/// <summary>
/// Whether or not to use asynchronous GPU commands in order to get the texture for the recorder.
/// </summary>
protected bool UseAsyncGPUReadback;

Texture2D m_ReadbackTexture;

/// <summary>
Expand All @@ -27,7 +32,7 @@ protected internal override bool BeginRecording(RecordingSession session)
if (!base.BeginRecording(session))
return false;

m_UseAsyncGPUReadback = SystemInfo.supportsAsyncGPUReadback;
UseAsyncGPUReadback = SystemInfo.supportsAsyncGPUReadback;
m_OngoingAsyncGPURequestsCount = 0;
m_DelayedEncoderDispose = false;
return true;
Expand All @@ -46,7 +51,7 @@ protected internal override void RecordFrame(RecordingSession session)

var renderTexture = input.OutputRenderTexture;

if (m_UseAsyncGPUReadback)
if (UseAsyncGPUReadback)
{
AsyncGPUReadback.Request(
renderTexture, 0, ReadbackTextureFormat, ReadbackDone);
Expand Down
12 changes: 12 additions & 0 deletions Editor/Sources/Helpers/UnityHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.Recorder;
using UnityEngine.SceneManagement;
using UnityObject = UnityEngine.Object;

namespace UnityEditor.Recorder
Expand Down Expand Up @@ -74,5 +75,16 @@ static void SetGameObjectVisibility(GameObject obj, bool visible)
}
}
}

internal static bool AreAllSceneDataLoaded()
{
for (int i = 0; i < SceneManager.sceneCount; ++i)
{
Scene s = SceneManager.GetSceneAt(i);
if (s.isLoaded == false)
return false;
}
return true;
}
}
}
86 changes: 52 additions & 34 deletions Editor/Sources/RecorderController.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
Expand Down Expand Up @@ -34,36 +34,25 @@ public RecorderController(RecorderControllerSettings settings)
m_Settings = settings;
m_SceneHook = new SceneHook(Guid.NewGuid().ToString());
}

/// <summary>
/// Start recording. Works only in Playmode.
/// Prepare the recording context by setting up the internal data and pausing the simulation.
/// Must be called before <see cref="StartRecording"/>.
/// </summary>
/// <returns>false if an error occured. The console will usually contains logs about the errors.</returns>
/// <exception cref="Exception">If not in Playmode.</exception>
/// <exception cref="NullReferenceException">If settings is null.</exception>
public bool StartRecording()
{
public void PrepareRecording()
{
if (!Application.isPlaying)
throw new Exception("Start Recording can only be called in Playmode.");

if (RecorderOptions.VerboseMode)
Debug.Log("Prepare Recording.");

if (m_Settings == null)
throw new NullReferenceException("Can start recording without prefs");

if (IsRecording())
{
if (RecorderOptions.VerboseMode)
Debug.Log("Recording was already started.");

return false;
}

if (RecorderOptions.VerboseMode)
Debug.Log("Start Recording.");

SceneHook.PrepareSessionRoot();

m_RecordingSessions = new List<RecordingSession>();

foreach (var recorderSetting in m_Settings.RecorderSettings)
{
if (recorderSetting == null)
Expand All @@ -84,8 +73,46 @@ public bool StartRecording()
continue;
}

if (!recorderSetting.Enabled)
{
if (RecorderOptions.VerboseMode)
Debug.Log("Ignoring disabled recorder '" + recorderSetting.name + "'");

continue;
}

var session = m_SceneHook.CreateRecorderSessionWithRecorderComponent(recorderSetting);

m_RecordingSessions.Add(session);
}
}

/// <summary>
/// Start recording. Works only in Playmode.
/// Must be called after <see cref="PrepareRecording"/> to setup the recording context.
/// </summary>
/// <returns>false if an error occured. The console will usually contains logs about the errors.</returns>
/// <exception cref="Exception">If not in Playmode.</exception>
/// <exception cref="NullReferenceException">If settings is null.</exception>
public bool StartRecording()
{
if (!Application.isPlaying)
throw new Exception("Start Recording can only be called in Playmode.");

if (IsRecording())
{
if (RecorderOptions.VerboseMode)
Debug.Log("Recording was already started.");

return false;
}

foreach (var recorderSetting in m_Settings.RecorderSettings)
{
var errors = new List<string>();

// This can be done only here as some recorders needs data from scenes.
// Example: Animation Recorder needs their target to exist.
if (!recorderSetting.ValidityCheck(errors))
{
foreach (var error in errors)
Expand All @@ -98,20 +125,11 @@ public bool StartRecording()
Debug.LogWarning("Recorder '" + recorderSetting.name +
"' has warnings and may not record properly.");
}
}

if (!recorderSetting.Enabled)
{
if (RecorderOptions.VerboseMode)
Debug.Log("Ignoring disabled recorder '" + recorderSetting.name + "'");

continue;
}

var session = m_SceneHook.CreateRecorderSessionWithRecorderComponent(recorderSetting);
if (RecorderOptions.VerboseMode)
Debug.Log("Start Recording.");

m_RecordingSessions.Add(session);
}

var success = m_RecordingSessions.Any() && m_RecordingSessions.All(r => r.SessionCreated() && r.BeginRecording());

return success;
Expand Down Expand Up @@ -163,4 +181,4 @@ internal IEnumerable<RecordingSession> GetRecordingSessions()
return m_SceneHook.GetRecordingSessions();
}
}
}
}
18 changes: 15 additions & 3 deletions Editor/Sources/RecorderControllerSettingsPreset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

namespace UnityEditor.Recorder
{
class RecorderControllerSettingsPreset : ScriptableObject
/// <summary>
/// Class that models a Recorder List (a stack of preset Recorder Settings instances) that you can save and load for reuse into a Recorder Window.
/// </summary>
public class RecorderControllerSettingsPreset : ScriptableObject
{
[SerializeField] Preset m_Model;
[SerializeField] List<Preset> m_RecorderPresets = new List<Preset>();
Expand All @@ -19,7 +22,12 @@ internal Preset[] recorderPresets
get { return m_RecorderPresets.ToArray(); }
}

internal static void SaveAtPath(RecorderControllerSettings model, string path)
/// <summary>
/// Saves the specified Recorder List to a file on disk. Note that this method doesn't save Scene references (such as a GameObject reference in Animation Recorder Settings).
/// </summary>
/// <param name="model">The Recorder List to save.</param>
/// <param name="path">The path on disk where to save the Recorder List. You must specify a path relative to the project.</param>
public static void SaveAtPath(RecorderControllerSettings model, string path)
{
var data = CreateInstance<RecorderControllerSettingsPreset>();

Expand Down Expand Up @@ -53,7 +61,11 @@ internal static void SaveAtPath(RecorderControllerSettings model, string path)
AssetDatabase.Refresh();
}

internal void AppyTo(RecorderControllerSettings prefs)
/// <summary>
/// Applies the current Recorder List to the specified RecorderControllerSettings instance.
/// </summary>
/// <param name="prefs">The RecorderControllerSettings instance to apply the Recorder List to.</param>
public void ApplyTo(RecorderControllerSettings prefs)
{
prefs.ReleaseRecorderSettings();

Expand Down
Loading

0 comments on commit ed22282

Please sign in to comment.