C# 从相机上截取屏幕快照,然后在(WaitForEndOffFrame)上禁用它是否正确?

C# 从相机上截取屏幕快照,然后在(WaitForEndOffFrame)上禁用它是否正确?,c#,unity3d,C#,Unity3d,我制作了这个非常简单的脚本,它应该用renderTexure连接到非活动的摄像头游戏对象。 如果摄影机游戏对象处于活动状态,则假定只将一帧录制到RenderExure,然后将其保存为.png的路径。之后,应禁用相机 public static string path; void Update() { StartCoroutine(SSOT()); } public static void SaveRTToFileToSharing() { RenderTexture

我制作了这个非常简单的脚本,它应该用renderTexure连接到非活动的摄像头游戏对象。 如果摄影机游戏对象处于活动状态,则假定只将一帧录制到RenderExure,然后将其保存为.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);
}
公共静态字符串路径;
无效更新()
{
启动程序(SSOT());
}
公共静态void SaveRTToFileToSharing()
{
RenderTexture rt=Resources.Load(@“Render Texure/ScreenShot”)作为RenderTexture;
RenderTexture.active=rt;
Texture2D tex=新的Texture2D(rt.width,rt.height,TextureFormat.RGB24,false);
tex.ReadPixels(新矩形(0,0,rt.width,rt.height),0,0);
//RenderTexture.active=null;
tex.Apply();
字节[]字节;
字节=tex.EncodeToPNG();
path=Application.persistentDataPath+“testshot.png”;
System.IO.File.writealBytes(路径,字节);
销毁(tex);
}
IEnumerator SSOT()
{
返回新的WaitForEndOfFrame();
SaveRTToFileToSharing();
gameObject.SetActive(false);
}

脚本按照我的预期工作,但我不确定它是否真的只录制了一帧或多帧。如果要更改任何内容,您会更改什么?

应该可以,因为您在启用对象的同一帧中停用了该对象

无论如何,为了确保我不会使用每帧调用的
Update
,只需将
startcroutine
调用移动到每次激活游戏对象时调用的

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);
    }
}
privaterendertexture-rt;
私有纹理2d-tex;
私有字符串路径;
私人空间()
{
//只做一次,并在游戏运行时将其保留
rt=(RenderTexture)Resources.Load(@“RenderTexture/ScreenShot”);
tex=新纹理2d(rt.width,rt.height,TextureFormat.RGB24,false);
path=Application.persistentDataPath+“testshot.png”;
}
私有void SaveRTToFileToSharing()
{
RenderTexture.active=rt;
tex.ReadPixels(新矩形(0,0,rt.width,rt.height),0,0);
//RenderTexture.active=null;
tex.Apply();
字节[]字节;
字节=tex.EncodeToPNG();
//这是异步进行的,因此您的游戏可以同时继续
使用(var fileStream=File.Open(路径,FileMode.OpenOrCreate,FileAccess.Write))
{
WriteAsync(字节,0,字节.长度);
}
}

谢谢,这是一些非常好的更改。我正在挖掘异步文件流,但它最终没有向目标写入任何比特,所以我回退到:file.writealBytes(path,bytes);