-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## [5.0.0] - 2023-09-19 ### Added - Tutorial in documentation to set up a Unity project with API scripting for starting recordings via a command line. ### Changed - Removed resolution automatic rounding to the nearest even number when Movie Recorder uses MP4 codec and "Match Window Size" output resolution. ### Fixed - Prevent video output from being corrupted when generated via a Recorder Clip run through a Scene loaded in Play mode. - Ensure the project uses the right RenderPipeline settings at all time: quality RenderPipeline settings or default RenderPipeline settings. - Ensure that the status messages at the bottom of the Recorder window are always readable even if the window is small.
- Loading branch information
Unity Technologies
committed
Sep 19, 2023
1 parent
618752c
commit 4ae66f5
Showing
23 changed files
with
451 additions
and
126 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using UnityEditor; | ||
using UnityEditor.Presets; | ||
using UnityEditor.Recorder; | ||
using UnityEngine; | ||
|
||
public class CommandLineRecorder : MonoBehaviour | ||
{ | ||
// The RecorderController starts and stops the recording. | ||
private RecorderController m_Controller; | ||
|
||
// The first frame to record. | ||
[SerializeField] private int m_startFrame; | ||
|
||
// The last frame to record. | ||
[SerializeField] private int m_endFrame; | ||
|
||
// The path to the Recorder Settings preset file to use for the recording. | ||
[SerializeField] private string m_presetPath; | ||
|
||
static RecorderSettings LoadRecorderSettingsFromPreset(string presetPath) | ||
{ | ||
// Load the Preset from the provided path. | ||
var preset = AssetDatabase.LoadAssetAtPath<Preset>(presetPath); | ||
|
||
// Use reflection to determine the type of the RecorderSettings to use | ||
// (for example a MovieRecorderSettings). | ||
var recorderSettingsTypes = | ||
TypeCache.GetTypesDerivedFrom<RecorderSettings>().ToList(); | ||
|
||
var recorderSettingsType = recorderSettingsTypes.SingleOrDefault( | ||
t => t.Name == preset.GetTargetTypeName()); | ||
|
||
if (recorderSettingsType == null) | ||
{ | ||
Debug.Log("Preset must be a subclass of RecorderSettings"); | ||
return null; | ||
} | ||
|
||
// Create a new RecorderSettings instance and apply the Preset to it. | ||
RecorderSettings outSettings = | ||
(RecorderSettings)ScriptableObject.CreateInstance(recorderSettingsType); | ||
|
||
preset.ApplyTo(outSettings); | ||
outSettings.name = preset.name; | ||
|
||
return outSettings; | ||
} | ||
|
||
void StartRecording(string presetPath, int startFrame, int endFrame) | ||
{ | ||
// Create RecorderSettings from the provided Preset path. | ||
RecorderSettings recorderSettings = LoadRecorderSettingsFromPreset(presetPath); | ||
recorderSettings.FrameRate = 60; | ||
|
||
// Create a new RecorderControllerSettings to set the start and end frame for | ||
// the recording session and add the RecorderSettings to it. | ||
var controllerSettings = ScriptableObject.CreateInstance<RecorderControllerSettings>(); | ||
controllerSettings.AddRecorderSettings(recorderSettings); | ||
controllerSettings.SetRecordModeToFrameInterval(startFrame, endFrame); | ||
|
||
// Create and setup a new RecorderController and start the recording. | ||
m_Controller = new RecorderController(controllerSettings); | ||
m_Controller.PrepareRecording(); | ||
m_Controller.StartRecording(); | ||
} | ||
|
||
void OnEnable() | ||
{ | ||
// This is called once when Unity enters PlayMode. | ||
StartRecording(m_presetPath, m_startFrame, m_endFrame); | ||
} | ||
|
||
void Update() | ||
{ | ||
// This is called on every frame when Unity is in PlayMode. | ||
if (m_Controller != null && !m_Controller.IsRecording()) | ||
{ | ||
// When the RecorderController has no more frame to record, stop | ||
// the recording and exit the PlayMode. | ||
m_Controller.StopRecording(); | ||
EditorApplication.ExitPlaymode(); | ||
} | ||
} | ||
|
||
static Dictionary<string, string> GetCommandLineArgs() | ||
{ | ||
string[] cmdLineParts = Environment.GetCommandLineArgs(); | ||
Dictionary<String, String> arguments = new Dictionary<string, string>(); | ||
|
||
// These are the 3 arguments this MonoBehaviour expects to start a recording. | ||
string[] args = { "-startFrame", "-endFrame", "-presetPath" }; | ||
|
||
var idx = 1; | ||
while (idx < cmdLineParts.Length) | ||
{ | ||
var part = cmdLineParts[idx]; | ||
if (args.Contains(part)) | ||
{ | ||
var argName = part.TrimStart('-'); | ||
arguments[argName] = cmdLineParts[idx + 1]; | ||
} | ||
|
||
idx++; | ||
} | ||
|
||
return arguments; | ||
} | ||
|
||
private void SetRecordingInfo(int startFrame, int endFrame, string presetPath) | ||
{ | ||
m_startFrame = startFrame; | ||
m_endFrame = endFrame; | ||
m_presetPath = presetPath; | ||
AssetDatabase.SaveAssets(); | ||
} | ||
|
||
public static void ExecuteCommandLine() | ||
{ | ||
// Parse the command line arguments to find the start and end frame and | ||
// the path to the Recorder Settings Preset file to use. | ||
var args = GetCommandLineArgs(); | ||
if (!args.TryGetValue("startFrame", out var startFrame)) | ||
throw new ArgumentException("[ERROR] Expected argument -startFrame"); | ||
|
||
if (!args.TryGetValue("endFrame", out var endFrame)) | ||
throw new ArgumentException("[ERROR] Expected argument -endFrame"); | ||
|
||
if (!args.TryGetValue("presetPath", out var presetPath)) | ||
throw new ArgumentException("[ERROR] Expected argument -presetPath"); | ||
|
||
// Find the GameObject that has the CommandLineRecorder MonoBehaviour attached | ||
// to it and set the recording information provided by the command line arguments. | ||
var sceneCommandLineRecorder = | ||
FindObjectsByType<CommandLineRecorder>(FindObjectsSortMode.None).First(); | ||
|
||
sceneCommandLineRecorder.SetRecordingInfo( | ||
Convert.ToInt32(startFrame), | ||
Convert.ToInt32(endFrame), | ||
presetPath); | ||
|
||
// Enter PlayMode: which starts the Recording (OnEnable) | ||
EditorApplication.EnterPlaymode(); | ||
} | ||
} |
Oops, something went wrong.