Unity基于Recoder的API写了一个随时录屏的工具

Tips:
需要有Recorder Package引用或存在在项目

复制代码
using UnityEngine;
using UnityEditor;
using UnityEditor.Recorder;
using UnityEditor.Recorder.Input;
using System.IO;
using System;

public class RecorderWindow : EditorWindow
{
    private RecorderController recorderController;
    private bool isRecording = false;
    private string outputPath = "Recordings";
    private string fileName = "Gameplay";
    private int resolutionWidth = 1920;
    private int resolutionHeight = 1080;
    private bool includeAudio = true;
    private bool showAdvanced = false;
    private int frameRate = 60;
    private bool autoTimestamp = true;
    private Vector2 scrollPosition;

    [MenuItem("Tools/Recorder Control")]
    public static void ShowWindow()
    {
        var window = GetWindow<RecorderWindow>("录制控制");
        window.minSize = new Vector2(350, 450);
        window.SetupRecorder();
    }

    private void SetupRecorder()
    {
        if (recorderController != null) return;

        var controllerSettings = ScriptableObject.CreateInstance<RecorderControllerSettings>();
        recorderController = new RecorderController(controllerSettings);
    }

    private void OnGUI()
    {
        scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);

        EditorGUILayout.Space(10);
        EditorGUILayout.LabelField("录制控制", EditorStyles.boldLabel);
        EditorGUILayout.Space(5);

        // Recording Status
        var status = isRecording ? "录制中" : "准备就绪";
        var statusColor = isRecording ? new Color(0.8f, 0.2f, 0.2f) : new Color(0.2f, 0.7f, 0.2f);
        var origColor = GUI.color;
        GUI.color = statusColor;
        EditorGUILayout.LabelField($"状态: {status}", EditorStyles.boldLabel);
        GUI.color = origColor;

        EditorGUILayout.Space(15);

        // Recording Controls
        EditorGUILayout.BeginHorizontal();
        if (GUILayout.Button(isRecording ? "停止录制" : "开始录制", GUILayout.Height(40)))
        {
            if (isRecording) StopRecording();
            else StartRecording();
        }

        if (GUILayout.Button("打开输出目录", GUILayout.Height(40)))
        {
            OpenOutputFolder();
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.Space(20);
        EditorGUILayout.LabelField("录制设置", EditorStyles.boldLabel);
        EditorGUILayout.Space(10);

        // Output Settings
        EditorGUILayout.BeginVertical("box");
        EditorGUILayout.LabelField("输出设置", EditorStyles.boldLabel);

        EditorGUILayout.BeginHorizontal();
        outputPath = EditorGUILayout.TextField("输出路径", outputPath);
        if (GUILayout.Button("浏览", GUILayout.Width(60)))
        {
            outputPath = EditorUtility.SaveFolderPanel("选择输出目录", outputPath, "");
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        fileName = EditorGUILayout.TextField("文件名称", fileName);
        autoTimestamp = EditorGUILayout.Toggle("添加时间戳", autoTimestamp, GUILayout.Width(150));
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.EndVertical();

        // Video Settings
        EditorGUILayout.BeginVertical("box");
        EditorGUILayout.LabelField("视频设置", EditorStyles.boldLabel);

        EditorGUILayout.BeginHorizontal();
        resolutionWidth = EditorGUILayout.IntField("宽度", resolutionWidth);
        resolutionHeight = EditorGUILayout.IntField("高度", resolutionHeight);
        EditorGUILayout.EndHorizontal();

        frameRate = EditorGUILayout.IntSlider("帧率", frameRate, 1, 120);
        includeAudio = EditorGUILayout.Toggle("包含音频", includeAudio);

        EditorGUILayout.EndVertical();

        // Advanced Settings
        showAdvanced = EditorGUILayout.Foldout(showAdvanced, "高级设置", true);
        if (showAdvanced)
        {
            EditorGUILayout.BeginVertical("box");
            EditorGUILayout.HelpBox("这些设置用于特殊需求,通常使用默认值即可", MessageType.Info);

            EditorGUILayout.Space(5);
            if (GUILayout.Button("重置为默认设置"))
            {
                ResetToDefaults();
            }

            EditorGUILayout.EndVertical();
        }

        EditorGUILayout.Space(20);
        EditorGUILayout.EndScrollView();

        // Footer
        EditorGUILayout.BeginVertical("box");
        EditorGUILayout.LabelField("快捷键: F9 - 开始/停止录制", EditorStyles.centeredGreyMiniLabel);
        EditorGUILayout.LabelField("输出目录: " + GetFullOutputPath(), EditorStyles.centeredGreyMiniLabel);
        EditorGUILayout.EndVertical();
    }

    private void StartRecording()
    {
        SetupRecorder();

        var controllerSettings = recorderController.Settings;
        controllerSettings.ClearRecorderSettings(); // Clear existing settings

        // Create video recorder
        var videoRecorder = ScriptableObject.CreateInstance<MovieRecorderSettings>();
        videoRecorder.name = "Gameplay Recorder";
        videoRecorder.Enabled = true;

        // Output settings
        videoRecorder.OutputFile = Path.Combine(outputPath, fileName);
        if (autoTimestamp)
        {
            videoRecorder.OutputFile += "_" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
        }

        // Resolution settings
        videoRecorder.ImageInputSettings = new GameViewInputSettings
        {
            OutputWidth = resolutionWidth,
            OutputHeight = resolutionHeight
        };

        // Video format
        videoRecorder.VideoBitRateMode = VideoBitrateMode.High;
        videoRecorder.OutputFormat = MovieRecorderSettings.VideoRecorderOutputFormat.MP4;

        // Audio settings
        if (includeAudio)
        {
            var audioRecorder = ScriptableObject.CreateInstance<AudioRecorderSettings>();
            audioRecorder.Enabled = true;
            controllerSettings.AddRecorderSettings(audioRecorder);
        }

        // Frame rate settings
        controllerSettings.SetRecordModeToManual();
        controllerSettings.FrameRate = frameRate;

        // Add video recorder
        controllerSettings.AddRecorderSettings(videoRecorder);

        // Start recording
        recorderController.PrepareRecording();
        recorderController.StartRecording();
        isRecording = true;

        Debug.Log($"录制已开始: {GetFullOutputPath()}.mp4");
    }

    private void StopRecording()
    {
        if (recorderController != null)
        {
            recorderController.StopRecording();
            Debug.Log($"录制已停止,文件保存至: {GetFullOutputPath()}.mp4");
        }
        isRecording = false;
    }

    private string GetFullOutputPath()
    {
        string fullPath = Path.Combine(Directory.GetCurrentDirectory(), outputPath, fileName);
        if (autoTimestamp)
        {
            fullPath += "_" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
        }
        return fullPath;
    }

    private void OpenOutputFolder()
    {
        string fullPath = Path.Combine(Directory.GetCurrentDirectory(), outputPath);
        if (!Directory.Exists(fullPath))
        {
            Directory.CreateDirectory(fullPath);
        }
        EditorUtility.RevealInFinder(fullPath);
    }

    private void ResetToDefaults()
    {
        outputPath = "Recordings";
        fileName = "Gameplay";
        resolutionWidth = 1920;
        resolutionHeight = 1080;
        includeAudio = true;
        frameRate = 60;
        autoTimestamp = true;
    }

    private void OnInspectorUpdate()
    {
        if (isRecording && recorderController != null)
        {
            Repaint();
        }
    }

    private void Update()
    {
        // Handle F9 key for recording
        if (Event.current != null && Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.F9)
        {
            if (isRecording) StopRecording();
            else StartRecording();
            Event.current.Use();
        }
    }

    private void OnDestroy()
    {
        if (isRecording)
        {
            StopRecording();
        }
    }
}
相关推荐
汤姆yu6 分钟前
基于springboot的在线答题练习系统
java·spring boot·后端·答题练习
我认不到你38 分钟前
JVM分析(OOM、死锁、死循环)(JProfiler、arthas、jdk调优工具(命令行))
java·linux·开发语言·jvm·spring boot
zhong liu bin43 分钟前
maven【maven】技术详解
java·ide·python·spring·maven·intellij-idea
七夜zippoe1 小时前
Java 技术支撑 AI 系统落地:从模型部署到安全合规的企业级解决方案(二)
java·人工智能·安全
孤狼程序员1 小时前
异常处理小妙招——1.别把“数据库黑话”抛给用户:论异常封装的重要性
java·数据库·mysql
java干货1 小时前
还在 @AfterEach 里手动 deleteAll()?你早就该试试这个测试数据清理 Starter 了
java·数据库·oracle
EQ-雪梨蛋花汤2 小时前
【踩坑记录】Unity 项目中 PlasticSCM 掩蔽列表引发的 文件缺失问题排查与解决
unity·游戏引擎
弗锐土豆2 小时前
编程基础-eclipse创建第一个程序
java·eclipse·helloworld·创建工程
Akshsjsjenjd3 小时前
Ansible 核心功能:循环、过滤器、判断与错误处理全解析
java·数据库·ansible
桦说编程3 小时前
使用注解写出更优雅的代码,以CFFU为例
java·后端·函数式编程