Unity截图生成图片 图片生成器 一键生成图片

news2024/11/20 10:42:36

使用Unity编辑器扩展技术实现快速截图功能

效果:请添加图片描述

里面没有什么太难的技术,直接上源码吧

  • 注意!代码需要放在Editor文件下才能正常运行
using System;
using UnityEditor;
using UnityEngine;

[ExecuteInEditMode]
public class Screenshot : EditorWindow
{
    int MaxShowSelectGo = 5;//最多显示选中的物体

    int resWidth = Screen.width * 4;
	int resHeight = Screen.height * 4;
    
	public Camera myCamera;
	int scale = 1;
    float delayCreateTime = 0.5f;
	string path = "";
	bool showPreview = true;
	RenderTexture renderTexture;
	GameObject[] selectGOs;
	bool isTransparent = true;
	bool isCaptureMultiple = false;
    // Add menu item named "My Window" to the Window menu
    [MenuItem("Tools/图片生成器")]
	public static void ShowWindow()
	{
		//Show existing window instance. If one doesn't exist, make one.
		EditorWindow editorWindow = EditorWindow.GetWindow(typeof(Screenshot));
		editorWindow.autoRepaintOnSceneChange = true;
		editorWindow.Show();
		editorWindow.title = "图片生成器";
	}

	float lastTime;


	void OnGUI()
	{
		EditorGUILayout.LabelField("分辨率", EditorStyles.boldLabel);
		resWidth = EditorGUILayout.IntField("宽", resWidth);
		resHeight = EditorGUILayout.IntField("高", resHeight);

        EditorGUILayout.Space();
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("默认设置", EditorStyles.boldLabel);
        if (GUILayout.Button("使用Game视图的分辨率"))
        {
            resHeight = (int)Handles.GetMainGameViewSize().y;
            resWidth = (int)Handles.GetMainGameViewSize().x;

        }

        if (GUILayout.Button("使用默认大小。H:1440,W:2560"))
        {
            resHeight = 1440;
            resWidth = 2560;
            scale = 1;
        }
        EditorGUILayout.EndHorizontal();
        
        EditorGUILayout.Space();

		scale = EditorGUILayout.IntSlider("尺寸", scale, 1, 15);

		EditorGUILayout.HelpBox("截图的默认模式是裁剪,所以选择合适的宽度和高度。比例是在不损失质量的情况下倍增或放大渲染的一个因素.", MessageType.None);
        EditorGUILayout.Space();
        EditorGUILayout.LabelField("截图分辨率为 " + resWidth * scale + " x " + resHeight * scale + " p", EditorStyles.boldLabel);

        EditorGUILayout.Space();

        EditorGUILayout.BeginHorizontal();
        GUILayout.Label("选择相机", EditorStyles.boldLabel);
		myCamera = EditorGUILayout.ObjectField(myCamera, typeof(Camera), true, null) as Camera;
		if (myCamera == null) myCamera = Camera.main;
		if (myCamera != null) myCamera.clearFlags = CameraClearFlags.SolidColor;

        isTransparent = EditorGUILayout.Toggle("透明背景", isTransparent);
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.HelpBox("选择要捕捉渲染的相机。勾选则背景透明", MessageType.None);

        EditorGUILayout.Space();

        isCaptureMultiple = EditorGUILayout.Toggle("一次性捕捉多个物体", isCaptureMultiple);
		if (isCaptureMultiple)
		{
            selectGOs = Selection.gameObjects;
            GUILayout.Label((selectGOs.Length == 0 ? "你还什么都没有选。使用鼠标选中场景中的物体,用Shift或者Ctrl多选。" : "当前选择物体数量:"+ selectGOs.Length), EditorStyles.boldLabel);
            int ShowSelectGo = 0;
            foreach (var item in selectGOs)
			{
                if (ShowSelectGo>=MaxShowSelectGo&& MaxShowSelectGo < selectGOs.Length)
                {
                    GUILayout.Label("......", EditorStyles.boldLabel);
                    break;
                }
                GUILayout.Label(item.name, EditorStyles.boldLabel);
                ShowSelectGo++;
            }
        }

        EditorGUILayout.Space();

        GUILayout.Label("保存路径", EditorStyles.boldLabel);

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.TextField(path, GUILayout.ExpandWidth(false));
        if (GUILayout.Button("选择路径", GUILayout.ExpandWidth(false)))
            path = EditorUtility.SaveFolderPanel("保存图片的路径", path, Application.dataPath);

        EditorGUILayout.EndHorizontal();
        EditorGUILayout.HelpBox("选择保存屏幕截图的文件夹", MessageType.None);
        EditorGUILayout.Space();

        delayCreateTime = EditorGUILayout.Slider("延时生成时间", delayCreateTime, 0.5f, 5);
        EditorGUILayout.HelpBox("请注意!时间越短,生成图片出错的概率就越高。建议调整为1", MessageType.None);
        if (GUILayout.Button("生成", GUILayout.MinHeight(60)))
		{
			if (path == "") path = EditorUtility.SaveFolderPanel("保存图片的路径", path, Application.dataPath);
			if (isCaptureMultiple)
			{
                StartTakeHiResShot();
            }
			else
			{
                TakeHiResShot();
                Application.OpenURL("file://" + path);
            }
            
        }

		EditorGUILayout.Space();
		EditorGUILayout.BeginHorizontal();

		if (GUILayout.Button("打开最后一个截图", GUILayout.MaxWidth(160), GUILayout.MinHeight(40)))
		{
			if (lastScreenshot != "")
			{
				Application.OpenURL("file://" + lastScreenshot);
				Debug.Log("Opening File " + lastScreenshot);
			}
		}

		if (GUILayout.Button("打开截图文件夹", GUILayout.MaxWidth(100), GUILayout.MinHeight(40)))
		{
			Application.OpenURL("file://" + path);
		}
		EditorGUILayout.EndHorizontal();
	}
    GameObject go = null;
    void StartTakeHiResShot()
	{
        if (selectGOs.Length==0)
        {
            EditorUtility.DisplayDialog("提示", "请注意!你没有选择任何物体,这不会生成图片。\n\n请取消勾选'一次性捕捉多个物体'这个选项生成单张图片.", "确定");
            return;
        }
        foreach (var item in selectGOs)
        {
            item.SetActive(false);
        }
        go = null;
        Take(0,0);
        //Take(0);
    }
    void Take(int index,float delayTime)
    {
        if (index < selectGOs.Length)
        {
            if (go != null) go.SetActive(false);
            selectGOs[index].SetActive(true);
            go = selectGOs[index];
            if (delayTime > delayCreateTime)
            {
                delayTime = 0;
                TakeHiResShot();
                index++;
            }
            EditorApplication.delayCall += () => { Take(index, delayTime + 0.1f); };
        }
        else
        {
            Application.OpenURL("file://" + path);
        }
    }
    void Take(int index)
    {
        if (index < selectGOs.Length)
        {
            if (go != null) go.SetActive(false);
            selectGOs[index].SetActive(true);
            go = selectGOs[index];
            //EditorApplication.delayCall += () =>
            //{
            //    TakeHiResShot(() => { Take(index + 1); });
            //};
            TakeHiResShot(() =>
            {
                Take(index + 1);
            });
        }
        else
        {
            Application.OpenURL("file://" + path);
        }
    }

    //private bool takeHiResShot = false;
    public string lastScreenshot = "";


	public string ScreenShotName(int width, int height)
	{

		string strPath = "";

		strPath = string.Format("{0}/screen_{1}x{2}_{3}.png",
							 path,
							 width, height,
									   System.DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"));
		lastScreenshot = strPath;

		return strPath;
	}


    public void TakeHiResShot(Action Callback= null)
	{
		Debug.Log("采取截图");
        int resWidthN = resWidth * scale;
        int resHeightN = resHeight * scale;
        RenderTexture rt = new RenderTexture(resWidthN, resHeightN, 24);
        myCamera.targetTexture = rt;

        TextureFormat tFormat;
        if (isTransparent)
            tFormat = TextureFormat.ARGB32;
        else
            tFormat = TextureFormat.RGB24;


        Texture2D screenShot = new Texture2D(resWidthN, resHeightN, tFormat, false);
        myCamera.Render();
        RenderTexture.active = rt;
        screenShot.ReadPixels(new Rect(0, 0, resWidthN, resHeightN), 0, 0);
        myCamera.targetTexture = null;
        RenderTexture.active = null;
        byte[] bytes = screenShot.EncodeToPNG();
        string filename = ScreenShotName(resWidthN, resHeightN);

        System.IO.File.WriteAllBytes(filename, bytes);
        Debug.Log(string.Format("截图如下: {0}", filename));
        //Application.OpenURL(filename);
        Callback?.Invoke();
    }
}

点击下载Demo

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1031832.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

上网行为监管软件(上网行为管理软件通常具有哪些功能)

在我们的日常生活中&#xff0c;互联网已经成为了我们获取信息、交流思想、进行工作和娱乐的重要平台。然而&#xff0c;随着互联网的普及和使用&#xff0c;网络安全问题也日益突出&#xff0c;尤其是个人隐私保护和网络行为的规范。在这个背景下&#xff0c;上网行为审计软件…

将自己的代码发布成可以pip安装的包

要将自己的Python代码打包并通过pip进行安装&#xff0c;可以按照以下步骤进行操作&#xff1a; 创建一个新的文件夹&#xff0c;并将您的Python代码放入其中。确保您的代码结构是标准的Python包结构&#xff0c;即包含__init__.py文件和其他可能的模块文件。 结构示例:your_p…

【LeetCode75】第六十一题 打家劫舍

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 这是力扣里一道关于动态规划的很经典的一道题。 那么首先呢我们扮演一个小偷&#xff0c;有一堆的房屋让我们偷&#xff0c;但是我们不能…

计算机竞赛 深度学习OCR中文识别 - opencv python

文章目录 0 前言1 课题背景2 实现效果3 文本区域检测网络-CTPN4 文本识别网络-CRNN5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习OCR中文识别系统 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;…

分享一个清理工具栏和插件的小工具

现在只要是经常用SolidWorks的&#xff0c;肯定是多多少少知道一些插件&#xff0c;有时候安装了很多个插件的时候&#xff0c;工具栏可能会乱串&#xff0c;而且还有可能出现插件删除了&#xff0c;但插件里面还能看到。 这其中的原因很简单&#xff0c;基本上都是反注册或者…

ArryList线程安全问题以及解决方案

arrayList是一个线程不安全的集合,在多线程情况下可能会引起数据不一致、数组越界等问题。下面具体列一下多线程情况下ArrayList会出现什么错误. 1.java.util.ConcurrentModificationException ConcurrentModificationException 中文意思就是并发修改异常&#xff0c;存在于并…

【从入门到起飞】JavaSE—方法引用

&#x1f38a;专栏【JavaSE】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【The truth that you leave】 &#x1f970;欢迎并且感谢大家指出我的问题 文章目录 &#x1f354;概述&#x1f354;注意&#x1f388;如何确定是否是…

电脑msvcr100.dll丢失的解决方法,找不到msvcr100.dll的修复方法分享

msvcr100.dll 丢失是一种常见的软件运行错误&#xff0c;通常会在运行某些程序时出现。这个问题可能是由于多种原因导致的&#xff0c;例如病毒感染、软件损坏、卸载应用程序时误删除文件等。为了解决这个问题&#xff0c;我们需要采取一些措施来恢复 msvcr100.dll 文件。 一、…

heic图片如何转为jpg格式

heic图片如何转为jpg格式&#xff1f;现阶段&#xff0c;在技术水平不断完善的基础上&#xff0c;图片质量越来越好了&#xff0c;且图片数量也越来越多。图片内容不断丰富&#xff0c;导致图片格式愈发多样化。为了能够保证图片的有效应用&#xff0c;我们有的时候需要将图片格…

一台PoE交换机可以为多少个设备提供供电?

如今在安防监控领域&#xff0c;许多网络设备都支持PoE供电。在网络监控工程中&#xff0c;为了节省布线成本并提高便捷性&#xff0c;大多数工程商选择使用PoE供电方案&#xff0c;也就是使用PoE交换机为监控摄像头提供电力。那么&#xff0c;一台功率输出以太网&#xff08;P…

可以创业,也可以副业的网上长期挣钱的项目

在这个飞速发展的互联网时代&#xff0c;越来越多的人开始尝试在网上创业或者寻找一份可持续的副业来增加收入。不过在网上赚钱的难度是比较大的&#xff0c;不是轻易就能做到的&#xff0c;所以不付出一番努力&#xff0c;没有悟性和执行力&#xff0c;那么是很难做好的&#…

MongoDB【部署 04】Windows系统实现MongoDB多磁盘存储

Windows系统实现多磁盘存储 1.为什么2.多磁盘存储2.1 数据库配置2.2 文件夹磁盘映射2.3 创建新的数据集 3.总结 1.为什么 这里仅针对只有一台Windows系统服务器的情景&#xff1a; 当服务器存储不足时&#xff0c;或者要接入更多的数据&#xff0c;就会挂载新磁盘&#xff0c…

Vim编辑器使用入门

目录 一、Vim 编辑器基础操作 二、Vim 编辑器进阶操作 三、Vim 编辑器高级操作 四、Vim 编辑器文件操作 五、Vim 编辑器文件管理 六、Vim 编辑器进阶技巧 七、Vim 编辑器增强功能 Vim的三种工作模式 一、Vim 编辑器基础操作 1.移动光标 - 光标的移动控制 移动光标有两…

JS手动实现发布者-订阅者模式

发布-订阅模式是一种对象间一对多的依赖关系&#xff0c;当一个对象的状态发送改变时&#xff0c;所有依赖于它的对象都将得到状态改变的通知。具体过程是&#xff1a;订阅者把自己想订阅的事件注册到调度中心&#xff0c;当发布者更新该事件时通知调度中心&#xff0c;由调度中…

python每日一题(模拟用户登录验证)

1、题目 预先设定正确用户名与密码&#xff0c;用来验证用户是否登录成功。 第一次&#xff1a; ① 输入用户名与密码&#xff0c;如果用户名与密码正确&#xff0c;则提示登录成功&#xff1b; ② 如果用户名错误&#xff08;不管密码是否正确&#xff09;&#xff0c;则需要重…

【NetEQ】读 《白话解读 WebRTC 音频 NetEQ 及优化实践》学习笔记

白话解读 WebRTC 音频 NetEQ 及优化实践webrtc 的重要模块 官方文档 :转载请标明出处:大神翻译 大神地址 : https://blog.csdn.net/lhl_blog/article/details/10993605GIPS NetEQ概述 GIPS NetEQ是一项专为IP电信系统开发的高级语音质量处理技术,其能够在大幅提高语音质量的…

ros 接收相机数据数据并发布

完整这个任务不需要用到python3 效果如下所示 环境 ROS1 python2.7 原始环境 无conda 或者conda deactivate 无conda 状态 pip install rospkg pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python4.2.0.3 代码 放在工程目录中 #!/usr/bin/env …

stm32学习笔记:OLED显示屏

一、OLED简介 OLED:有机发光二极管&#xff0c;供电∶3~5.5V&#xff0c;通信协议︰I2C/SPI&#xff0c;分辨率∶12864 二、常用的调试方式 串口调试∶通过串口通信&#xff0c;将调试信息发送到电脑端&#xff0c;电脑使用串口助手显示调试信息 显示屏调试∶直接将显示屏连接…

龙讯旷腾机器学习力场PWMLFF V0.1.0——优化件lammps接口,提供主动学习方案

PWMLFF&#xff08;机器学习力场&#xff09;手册 http://doc.lonxun.com/PWMLFF/ 我们都知道从第一性原理出发的分子动力学&#xff08;Ab Initio Molecular Dynamics, AIMD&#xff09;计算非常精确&#xff0c;但需要消耗大量时间和计算资源&#xff0c;能模拟的空间尺度和…

代码随想录算法训练营第59天 | ● 503.下一个更大元素II ● 42. 接雨水

文章目录 前言一、503.下一个更大元素II二、42. 接雨水总结 前言 单调栈&#xff1b; 一、503.下一个更大元素II 循环的问题&#xff1a;1.多建立一个数组 2.采用取模的方法&#xff1b; 问题&#xff1a;采用取模&#xff0c;后面的值会被前面的覆盖掉吗&#xff1f; 答&am…