Unity Recorder script freezes GameView,Scene and Console

Hello guys,
I have been trying to create my own recorder script but i have 1 major issue, when ever i try to run it, the Game view, Scene and Console freezes. I have no idea why, but the last thing i see in the console is:
Screenshot 2025-03-18 at 12.24.19 PM
Here is my Recorder script:

using UnityEngine;
using UnityEditor.Recorder;
using UnityEditor.Recorder.Input;
using UnityEngine.SceneManagement;
using System;
using System.IO;
using System.Collections;

public class RecorderControl : MonoBehaviour
{
    private RecorderController recorderController;
    private MovieRecorderSettings movieRecorderSettings;
    private string sceneName;
    private string sessionFolder;
    public int recordingIndex = 1; // Starts at 1 for each session

    [SerializeField] private float recordingInterval = 70f;
    public int maxRecordings = 5; // Number of recordings before quitting

    void Awake()
    {   
        sceneName = GetSceneName();
        Application.runInBackground = true;
        sessionFolder = CreateNewRecordingFolder();
        Debug.Log($"Created recording folder: {sessionFolder}");
        SetupRecorderInitial();
    }

    // Set up the recorder only once at startup
    void SetupRecorderInitial()
    {
        var recorderControllerSettings = ScriptableObject.CreateInstance<RecorderControllerSettings>();
        recorderControllerSettings.FrameRate = 60;
        recorderControllerSettings.CapFrameRate = true;
        recorderControllerSettings.FrameRatePlayback = FrameRatePlayback.Constant;
        recorderController = new RecorderController(recorderControllerSettings);

        movieRecorderSettings = ScriptableObject.CreateInstance<MovieRecorderSettings>();
        movieRecorderSettings.name = sceneName;
        movieRecorderSettings.Enabled = true;
        
        var gameViewSettings = new GameViewInputSettings
        {
            OutputWidth = 1080,
            OutputHeight = 1920
        };
        movieRecorderSettings.ImageInputSettings = gameViewSettings;
        movieRecorderSettings.AudioInputSettings.PreserveAudio = true;
        movieRecorderSettings.RecordMode = RecordMode.TimeInterval;
        movieRecorderSettings.StartTime = 0f;
        movieRecorderSettings.EndTime = recordingInterval;
        
        recorderControllerSettings.AddRecorderSettings(movieRecorderSettings);
        
        StartCoroutine(PrepareRecorder());
    }

    IEnumerator PrepareRecorder()
    {
        yield return null;
        recorderController.PrepareRecording();
        Debug.Log("Recorder prepared.");
    }

    // Instead of reinitializing the recorder, update the OutputFile and re-prepare
    public IEnumerator SetupRecorderForNewRecording()
    {
        string fileName = $"{sceneName}_{recordingIndex}.mp4";
        movieRecorderSettings.OutputFile = $"{sessionFolder}/{fileName}";
        Debug.Log($"Setting up new recording: {fileName}");
        yield return StartCoroutine(PrepareRecorder());
    }

    public void StartRecording()
    {
        if (recorderController.IsRecording())
        {
            Debug.LogWarning("Recording is already in progress.");
            return;
        }
        Debug.Log($"Starting recording: {sceneName}_{recordingIndex}.mp4 (Auto stops after {recordingInterval} sec).");
        recorderController.StartRecording();
    }

    public void ForceStopRecording()
    {
        if (recorderController.IsRecording())
        {
            recorderController.StopRecording();
            Debug.LogError($"Recording {sceneName}_{recordingIndex}.mp4 stopped after {recordingInterval} seconds.");
            recordingIndex++; // Increment for next recording
        }
    }

    public void QuitGame()
    {
        Debug.LogError("Quitting Unity...");
#if UNITY_EDITOR
        UnityEditor.EditorApplication.isPlaying = false; // Stop play mode in Editor
#else
        Application.Quit();
#endif
    }

    string GetSceneName()
    {
        return SceneManager.GetActiveScene().name;
    }

    string CreateNewRecordingFolder()
    {
        string basePath = Path.Combine(Application.dataPath, "../Recordings/");
        string sessionName = $"Session_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}";
        string fullPath = Path.Combine(basePath, sessionName);
        if (!Directory.Exists(fullPath))
        {
            Directory.CreateDirectory(fullPath);
        }
        return fullPath;
    }
}

And here is a scirpt where i use it:

void Start()
    {
        goal = GameObject.FindGameObjectWithTag("Goal");
        hook = canvaHook.transform.GetChild(0).gameObject;
        rc = rcGO.GetComponent<RecorderControl>();
        MatchSetUp();
        StartCoroutine(MatchLoop());
    }
    IEnumerator MatchLoop()
    {   
        while (rc.recordingIndex <= rc.maxRecordings) // loop to keep matches going
        {
            float interval = 65f + timeToWait; 

            float startTime = Time.time;
            float endTime = startTime + interval;

            Debug.Log($"Waiting for {interval} seconds -> {Time.time}");

            // Precise waiting loop
            while (Time.time < endTime)
            {
                yield return null; // Wait for the next frame without blocking
            }
            rc.ForceStopRecording();

            // Execute MatchSetUp precisely at the correct time
            Debug.Log($"Starting new match at -> {Time.time}");
            MatchSetUp();
        }
        Debug.LogError($"All {rc.maxRecordings} recordings completed. Exiting game...");
        yield return null;
        rc.QuitGame();
    }
    IEnumerator StartCountDown(float timeToWait)
    {   
        // Capture the exact start time
        float startTime = Time.time;
        float endTime = startTime + timeToWait;

        // Wait until the precise end time is reached
        while (Time.time < endTime)
        {
            yield return null; // allow Unity to continue updating frames
        }

        // Immediately execute after exact time elapsed
        Debug.Log($"Timer End -> {Time.time}");
        ResetTimer();
        UnFreezeBallz();
        RestartUIShower();
        yield return StartCoroutine(rc.SetupRecorderForNewRecording());
        rc.StartRecording();
        Debug.Log($"Game Start -> {Time.time}");
    }
    void MatchSetUp()
    {   
        sp.jsonDataCounter ++;
        Debug.Log($"Timer Start -> {Time.time}");
        StartCoroutine(StartCountDown(timeToWait));
        Debug.Log($"UpdateScene Start -> {Time.time}");
        UpdateScene();
    }

I can provide more information if needed, but i dont know what can help, so if you need something more just ask :smile:

Probably one of your while loops is locking up, such as if you miscompute endTime. Attach the debugger and find out!

Unity will lock up 100% of the time EVERY millisecond your scripting code is running.

Nothing will render, no input will be processed, no Debug.Log() will come out, no GameObjects or transforms will appear to update.

Absolutely NOTHING will happen… until your code either:

  • returns from whatever function it is running

  • yields from whatever coroutine it is running

As long as your code is looping, Unity isn’t going to do even a single frame of change. Nothing.

No exceptions.

“Yield early, yield often, yield like your game depends on it… it does!” - Kurt Dekker

Here’s a handy tool that might help you track down unknown infinite loops: