Unity RenderTexture的保存和多线程

2024-03-30 16:08

本文主要是介绍Unity RenderTexture的保存和多线程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在Unity中如果要保存相机图片,我们最常用的方法是首先把RenderTexture转化成Texture2D,如下:

Texture2D texture2D = null;
texture2D = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.ARGB32, false);
var previous = RenderTexture.active;
RenderTexture.active = renderTexture;
texture2D.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
RenderTexture.active = previous;
texture2D.Apply();
void Awake()
{targetRenderTexture = new RenderTexture((int)(normalSize), (int)(normalSize), 0 , RenderTextureFormat.ARGB32);//, RenderTextureFormat.Defaultint quality = QualitySettings.GetQualityLevel();if (quality > 0)targetRenderTexture.antiAliasing = 4;elsetargetRenderTexture.antiAliasing = 1;
}

RenderTexture创建部分

然后再把图片保存成二进制格式进行保存,如下:

byte[] bytes = txtureSmall.EncodeToPNG();
try
{string forder = GetFileDirectory(path);bool exists = System.IO.Directory.Exists(forder);if (!exists)System.IO.Directory.CreateDirectory(forder);System.IO.File.WriteAllBytes(path, data);
}
catch (Exception ee)
{Debug.Log("文件写入失败:" + path + " Error:" + ee.Message);
}

如果是在保存进度,场景切换等允许卡顿的地方操作是没有问题的。

如果是在不允许有卡顿感的操作中就是大问题了。

经过分析主要来自EncodeToPNG函数,耗费了大量CPU。

那么如果我们让他在别的进程运行,游戏就不会有卡顿感了。

马上进行测试:

		new System.Threading.Thread(() =>{这里处理上面的逻辑。}).Start();

发现不能在其他进程里处理RenderTexture,txtureSmall.EncodeToPNG,会报出
…… can only be called from the main thread.

那么怎么做呢,其实Unity提供了其他的方法来做这样事情。

下面做一个记录

		int nw = rendertxture.width;int nh = rendertxture.height;//filesavepath = filename;GraphicsFormat format = rendertxture.graphicsFormat;UnityEngine.Rendering.AsyncGPUReadbackRequest request = UnityEngine.Rendering.AsyncGPUReadback.Request(rendertxture, 0 );yield return 0;while (!request.done){yield return new WaitForEndOfFrame();}if (request.hasError){Debug.Log("GPU readback error detected.");yield break;}byte[] array = request.GetData<byte>().ToArray();Task.Run(() =>{
#if UNITY_EDITORDebug.Log("保存进度图:" + filename);
#endifbyte[] datas = ImageConversion.EncodeArrayToPNG(array, format, (uint)nw, (uint)nh);CFunc.StreamWriter(filename, datas);});

这样主线程就不会卡顿了。

经过一段时间测试后发现
AsyncGPUReadbackRequest的函数,可能会出现报错 This GfxDevice does not support asynchronous readback
发现报错了图片也能显示出来。匪夷所思
然后通过SystemInfo.supportsAsyncGPUReadback函数来判断发现也是False,说明不支持,不支持为说明图可以显示出来呢。

所以研究了下,直接可以通过拿出RenderText的Texture2D,获取到GetPixeds32,然后再放入多线程处理。代码如下,可能速度稍微慢一些。

	Texture2D saveToTexture(RenderTexture renderTexture){Texture2D texture2D = null;texture2D = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.ARGB32, false);var previous = RenderTexture.active;RenderTexture.active = renderTexture;texture2D.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);RenderTexture.active = previous;texture2D.Apply();return texture2D;}Texture2D txture = saveToTexture(targetRenderTexture);Color32[] array = txture.GetPixels32();//这里如果renderTexture不是RenderTextureFormat.ARGB32,在IOS中好像是BGRA,会导致获取保存的颜色变色,原因未知.GameObject.DestroyImmediate(txture);Task.Run(() =>{
#if UNITY_EDITORDebug.Log("保存进度图:" + filename);
#endifbyte[] bytes = ImageConversion.EncodeArrayToPNG(array, format, (uint)nw, (uint)nh);CFunc.StreamWriter(filename, bytes);pone.ok = true;});

相关技术资料
https://docs.unity3d.com/ScriptReference/ImageConversion.EncodeArrayToPNG.html
https://forum.unity.com/threads/asyncgpureadbackrequest-and-encodetopng.551314/
https://forum.unity.com/threads/using-the-job-system-to-save-images.522837/

这篇关于Unity RenderTexture的保存和多线程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/861948

相关文章

Python多线程实现大文件快速下载的代码实现

《Python多线程实现大文件快速下载的代码实现》在互联网时代,文件下载是日常操作之一,尤其是大文件,然而,网络条件不稳定或带宽有限时,下载速度会变得很慢,本文将介绍如何使用Python实现多线程下载... 目录引言一、多线程下载原理二、python实现多线程下载代码说明:三、实战案例四、注意事项五、总结引

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

Python多线程应用中的卡死问题优化方案指南

《Python多线程应用中的卡死问题优化方案指南》在利用Python语言开发某查询软件时,遇到了点击搜索按钮后软件卡死的问题,本文将简单分析一下出现的原因以及对应的优化方案,希望对大家有所帮助... 目录问题描述优化方案1. 网络请求优化2. 多线程架构优化3. 全局异常处理4. 配置管理优化优化效果1.

C#和Unity中的中介者模式使用方式

《C#和Unity中的中介者模式使用方式》中介者模式通过中介者封装对象交互,降低耦合度,集中控制逻辑,适用于复杂系统组件交互场景,C#中可用事件、委托或MediatR实现,提升可维护性与灵活性... 目录C#中的中介者模式详解一、中介者模式的基本概念1. 定义2. 组成要素3. 模式结构二、中介者模式的特点

Qt中实现多线程导出数据功能的四种方式小结

《Qt中实现多线程导出数据功能的四种方式小结》在以往的项目开发中,在很多地方用到了多线程,本文将记录下在Qt开发中用到的多线程技术实现方法,以导出指定范围的数字到txt文件为例,展示多线程不同的实现方... 目录前言导出文件的示例工具类QThreadQObject的moveToThread方法实现多线程QC

RabbitMQ消费端单线程与多线程案例讲解

《RabbitMQ消费端单线程与多线程案例讲解》文章解析RabbitMQ消费端单线程与多线程处理机制,说明concurrency控制消费者数量,max-concurrency控制最大线程数,prefe... 目录 一、基础概念详细解释:举个例子:✅ 单消费者 + 单线程消费❌ 单消费者 + 多线程消费❌ 多

Javaee多线程之进程和线程之间的区别和联系(最新整理)

《Javaee多线程之进程和线程之间的区别和联系(最新整理)》进程是资源分配单位,线程是调度执行单位,共享资源更高效,创建线程五种方式:继承Thread、Runnable接口、匿名类、lambda,r... 目录进程和线程进程线程进程和线程的区别创建线程的五种写法继承Thread,重写run实现Runnab

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.

python多线程并发测试过程

《python多线程并发测试过程》:本文主要介绍python多线程并发测试过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、并发与并行?二、同步与异步的概念?三、线程与进程的区别?需求1:多线程执行不同任务需求2:多线程执行相同任务总结一、并发与并行?1、