使用ScreenCapture.CaptureScreenshot

时间:2017-09-29 05:29:26

标签: c# ios unity3d screenshot

我一直试图拍摄截图,然后立即使用它来显示某种预览,有时候它会起作用,有时却没有,我目前不在工作而且我没有在这台计算机上有统一性,所以我会尝试在运行中重新创建它(这里和那里可能存在一些语法错误)

public GameObject screenshotPreview;

public void TakeScreenshot () {

        string imageName = "screenshot.png";

        // Take the screenshot
        ScreenCapture.CaptureScreenshot (imageName);

        // Read the data from the file
        byte[] data = File.ReadAllBytes(Application.persistentDataPath + "/" + imageName);

        // Create the texture
        Texture2D screenshotTexture = new Texture2D(Screen.width, Screen.height);

        // Load the image
        screenshotTexture.LoadImage(data);

        // Create a sprite
        Sprite screenshotSprite = Sprite.Create (screenshotTexture, new Rect(0, 0, Screen.width, Screen.height), new Vector2(0.5f, 0.5f) );

        // Set the sprite to the screenshotPreview
        screenshotPreview.GetComponent<Image> ().sprite = screenshotSprite;

}

据我所知,ScreenCapture.CaptureScreenshot不是异步的,因此在我尝试加载数据之前应该已经写好了图像,但是问题就像我之前说的那样,有些时候它不起作用并且它加载了一个带有红色问号的8x8纹理,这显然是纹理无法加载但文件应该已经存在,所以我无法理解为什么它没有正确加载。

我尝试过的另一件事(令人恶心,但我已经厌倦了这个并且耗尽了想法)是将更新方法放入等待一段时间,然后执行代码来加载数据并创建纹理,精灵和显示它,但即便如此,它失败了一些时间,比以前更少但它仍然失败,这使我相信即使文件创建它还没有完成beign写,有没有人知道一个变通方法这个?任何建议表示赞赏。

作为额外信息,此项目正在iOS设备中运行。

3 个答案:

答案 0 :(得分:1)

已知ScreenCapture.CaptureScreenshot函数存在许多问题。 Here是另一个。

以下是doc

的引用
  

在Android上,此功能立即返回。结果截图   稍后会有。

iOS行为没有记录,但我们可以假设iOS上的行为相同。在尝试读取/加载屏幕截图之前,请等待几帧。

public IEnumerator TakeScreenshot()
{

    string imageName = "screenshot.png";

    // Take the screenshot
    ScreenCapture.CaptureScreenshot(imageName);

    //Wait for 4 frames
    for (int i = 0; i < 5; i++)
    {
        yield return null;
    }

    // Read the data from the file
    byte[] data = File.ReadAllBytes(Application.persistentDataPath + "/" + imageName);

    // Create the texture
    Texture2D screenshotTexture = new Texture2D(Screen.width, Screen.height);

    // Load the image
    screenshotTexture.LoadImage(data);

    // Create a sprite
    Sprite screenshotSprite = Sprite.Create(screenshotTexture, new Rect(0, 0, Screen.width, Screen.height), new Vector2(0.5f, 0.5f));

    // Set the sprite to the screenshotPreview
    screenshotPreview.GetComponent<Image>().sprite = screenshotSprite;

}

请注意,您必须使用StartCoroutine(TakeScreenshot());来调用此功能。

如果不起作用,请不要使用此功能。这是另一种在Unity中获取和保存屏幕截图的方法:

IEnumerator captureScreenshot()
{
    yield return new WaitForEndOfFrame();

    string path = Application.persistentDataPath + "Screenshots/"
            + "_" + screenshotCount + "_" + Screen.width + "X" + Screen.height + "" + ".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);
    screenImage.Apply();
    //Convert to png
    byte[] imageBytes = screenImage.EncodeToPNG();

    //Save image to file
    System.IO.File.WriteAllBytes(path, imageBytes);
}

答案 1 :(得分:0)

我在文档中看不到任何说不是异步的内容。事实上,对于Android(如果我正确地阅读它),它明确地说它是异步的。

那就是说,在找不到文件的时候我会尝试拖延。把它扔进协程并

FileInfo yourFile = new FileInfo("YourFile.png");
while (File.Exists(yourFile.name) || IsFileLocked(yourFile)) 
    yield return null;

IsFileLocked

您还可以尝试在其中放入一些调试检查以查看文件出现之前需要多长时间(秒或帧)(假设它出现)。

编辑:正如derHugo指出的那样,文件存在并不意味着文件已经准备就绪。我编辑了代码来处理它!但它仍然不包括文件已存在的情况,在这种情况下,您可能需要动态文件名,如时间戳,或者您想先删除文件!

答案 2 :(得分:0)

程序员的代码通过如下调用成功工作。它设计为协程,因此不会干扰帧速率。因此,它应该被称为协程。确保CallerObject继承自“ MonoBehaviour”。

 public class CallerObject : MonoBehaviour
{
    public void Caller()
    {
        String imagePath = Application.persistentDataPath + "/image.png";
        StartCoroutine(captureScreenshot(imagePath));
    }


    IEnumerator captureScreenshot(String imagePath)
    {
        yield return new WaitForEndOfFrame();
        //about to save an image capture
        Texture2D screenImage = new Texture2D(Screen.width, Screen.height);


        //Get Image from screen
        screenImage.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
        screenImage.Apply();

        Debug.Log(" screenImage.width" + screenImage.width + " texelSize" + screenImage.texelSize);
        //Convert to png
        byte[] imageBytes = screenImage.EncodeToPNG();

        Debug.Log("imagesBytes=" + imageBytes.Length);

        //Save image to file
        System.IO.File.WriteAllBytes(imagePath, imageBytes);
    }
}
相关问题