问题描述
我尝试了每种变体: http://wiki.unity3d.com/index.php/ScreenCapture 毕竟,简单的Application.Capturescreenshot(...)最少.
I have tried each of variants: http://wiki.unity3d.com/index.php/ScreenCaptureAfterall, simple Application.Capturescreenshot(...) is the least laggy.
请告诉我,如何拍摄屏幕截图而不会出现任何滞后?Android上的许多游戏都具有此功能,因此并非不可能.
Please, tell me, How I can take screenshots without ANY lags?Lots of games on Android has thiis feature, so it's not impossible.
推荐答案
拍照时滞后的原因是您尝试同时执行所有步骤的时间在每个步骤之后没有 等待.要解决此问题,您执行一个操作,然后等待许多帧,然后执行下一个操作,然后再次等待.如果您决定在游戏过程中保存图片,请使用线程保存图片. EncodeToPNG()
是另一个问题,但是稍后我将讨论另一个解决方案.
The cause of lag while taking picture is when you try to perform all steps at the same time without waiting after each step. To fix this, you perform one action and wait for many frames then perform the next action then wait again. And if you decide to save the picture during game-play, use Thread to save the picture. EncodeToPNG()
is another problem but I will talk about another solution for it later on.
如果您想进行屏幕截图然后在游戏运行时立即显示,则下面的代码非常有用.它将正确显示图片,然后大约需要1.5秒钟来保存文件.
The code below is good if you want to take screen shot then display it right away while game is running.It will take picture right way then take about 1.5 seconds to save the file.
IEnumerator screenShotCoroutine()
{
yield return new WaitForEndOfFrame();
string path = Application.persistentDataPath + "/DrukaloScreenshot.png";
Texture2D screenImage = new Texture2D(Screen.width, Screen.height);
//Get Image from screen
screenImage.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
//Wait for a long time
for (int i = 0; i < 15; i++)
{
yield return null;
}
screenImage.Apply();
//Wait for a long time
for (int i = 0; i < 15; i++)
{
yield return null;
}
//Convert to png(Expensive)
byte[] imageBytes = screenImage.EncodeToPNG();
//Wait for a long time
for (int i = 0; i < 15; i++)
{
yield return null;
}
//Create new thread then save image to file
new System.Threading.Thread(() =>
{
System.Threading.Thread.Sleep(100);
File.WriteAllBytes(path, imageBytes);
}).Start();
}
如果要拍照,并且不需要立即显示图片,则可以将图片另存为原始 Texture2D
,然后在要稍后再访问/加载/显示图片,可以从文件中阅读,然后稍后将其转换为 PNG .原因是EncodeToPNG()
非常昂贵,因此,如果您不需要立即使用图片,则无需将其转换为png.您只有真正需要为 png 时,才能这样做.因此,现在我们可以将其保存为" .t2D ",然后再加载并将其转换为" .png ".
If you want to take the picture and you are not required to display the image right away, you can save the picture as raw Texture2D
, then when you want to access/load/display the picture later on, you can read it from file then convert it to PNG later on. The reason for this is that EncodeToPNG()
is very expensive so if you don't need the picture right away, there is no need to convert it to png. You can do that only when you actually need it as png. So now we can just save it as ".t2D" then load it after and convert the loaded image to ".png".
另存为Texture2D" .t2D "
Save as Texture2D ".t2D"
IEnumerator screenShotCoroutine()
{
yield return new WaitForEndOfFrame();
string path = Application.persistentDataPath + "/DrukaloScreenshot.t2D";
Texture2D screenImage = new Texture2D(Screen.width, Screen.height);
//Get Picture
screenImage.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
//Wait for a long time
for (int i = 0; i < 15; i++)
{
yield return null;
}
screenImage.Apply();
//Wait for a long time
for (int i = 0; i < 15; i++)
{
yield return null;
}
byte[] rawData = screenImage.GetRawTextureData();
//Wait for a long time
for (int i = 0; i < 15; i++)
{
yield return null;
}
//Create new thread then save image
new System.Threading.Thread(() =>
{
System.Threading.Thread.Sleep(100);
File.WriteAllBytes(path, rawData);
}).Start();
}
然后,当您实际需要图像时,加载Texture2D" .t2D ",然后将其隐藏为" .png ",然后删除旧的"". t2D ".
Then when you actually need the image, load Texture2D ".t2D" and then covert it to ".png" followed by deleting the old ".t2D".
IEnumerator screenShotCoroutine()
{
string path = Application.persistentDataPath + "/DrukaloScreenshot.t2D";
string newPath = Application.persistentDataPath + "/DrukaloScreenshot.png";
Texture2D screenImage = new Texture2D(Screen.width, Screen.height);
byte[] rawData = null;
//Create new thread then Load image
new System.Threading.Thread(() =>
{
System.Threading.Thread.Sleep(100);
rawData = File.ReadAllBytes(path);
}).Start();
//Wait for a long time
for (int i = 0; i < 9; i++)
{
yield return null;
}
//Put loaded bytes to Texture2D
screenImage.LoadRawTextureData(rawData);
//Wait for a long time
for (int i = 0; i < 9; i++)
{
yield return null;
}
screenImage.Apply();
//Wait for a long time
for (int i = 0; i < 9; i++)
{
yield return null;
}
//convert to png
byte[] pngByte = screenImage.EncodeToPNG();
//Wait for a long time
for (int i = 0; i < 9; i++)
{
yield return null;
}
//Do whatever you want with the png file(display to screen or save as png)
//Create new thread and Save the new png file, then Delete Old image(DrukaloScreenshot.t2D)
new System.Threading.Thread(() =>
{
System.Threading.Thread.Sleep(100);
File.WriteAllBytes(newPath, pngByte); //Save the new png file(DrukaloScreenshot.png)
File.Delete(path); //Delete old file (DrukaloScreenshot.t2D)
}).Start();
}
这篇关于毫无延迟地在Unity3D中拍摄屏幕截图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!