我制作了这个非常简单的脚本,该脚本应附加到带有RenderTexure的无活动相机游戏对象上。如果相机游戏对象处于活动状态,则该假设仅将一个帧记录到RenderTexure,然后将其保存到一个.png的路径中。之后应禁用相机。
public static string path;
void Update()
{
StartCoroutine(SSOT());
}
public static void SaveRTToFileToSharing()
{
RenderTexture rt = Resources.Load<RenderTexture>(@"Render Texure/ScreenShot") as RenderTexture;
RenderTexture.active = rt;
Texture2D tex = new Texture2D(rt.width, rt.height, TextureFormat.RGB24, false);
tex.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
//RenderTexture.active = null;
tex.Apply();
byte[] bytes;
bytes = tex.EncodeToPNG();
path = Application.persistentDataPath + "Test Shot.png";
System.IO.File.WriteAllBytes(path, bytes);
Destroy(tex);
}
IEnumerator SSOT()
{
yield return new WaitForEndOfFrame();
SaveRTToFileToSharing();
gameObject.SetActive(false);
}
该脚本按照我的预期工作,但我不确定它是否真的只记录一帧或更多帧。如果您要更改任何东西,您会更改什么?
应该没关系,因为您在启用的同一帧中停用对象。
无论如何只是为了确保我而不是使用Update
,这就是每一个帧,只需将StartCoroutine
调用到OnEnable
,而每次都称为游戏对象。
private void OnEnable()
{
StartCoroutine(SSOT());
}
为了使其更具性能,您只能做几件事并重用它们 - 取决于您的优先级:如果您的优先级是很少的记忆使用情况,并且性能对屏幕截图无关紧要,那么您就可以了当然。否则我可能会像
那样做private RenderTexture rt;
private Texture2D tex;
private string path;
private void Awake ()
{
// Do this only once and keep it around while the game is running
rt = (RenderTexture) Resources.Load<RenderTexture>(@"Render Texure/ScreenShot");
tex = new Texture2D(rt.width, rt.height, TextureFormat.RGB24, false);
path = Application.persistentDataPath + "Test Shot.png";
}
private void SaveRTToFileToSharing()
{
RenderTexture.active = rt;
tex.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
//RenderTexture.active = null;
tex.Apply();
byte[] bytes;
bytes = tex.EncodeToPNG();
// This happens async so your game can continue meanwhile
using (var fileStream = File.Open(path, FileMode.OpenOrCreate, FileAccess.Write))
{
fileStream.WriteAsync(bytes, 0, bytes.Length);
}
}