Capture and save screenshot with ScreenCapture.CaptureScreenshot

前端 未结 3 581
感动是毒
感动是毒 2021-01-15 19:14

I\'ve been trying to take a screenshot and then immediately after, use it to show some sort of preview and some times it works and some times it doesn\'t, I\'m currently not

相关标签:
3条回答
  • 2021-01-15 19:19

    I see nothing in the docs that says its not Async. In fact, for Android (if I'm reading this correctly), it explicitly says it's async.

    That said, I'd try stalling while the file is not found. Throw it in a coroutine and

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

    IsFileLocked

    You could also try throwing in some debug checks in there to see how long it takes (seconds or frames) before the file appears (assuming it ever appears).

    Edit: As derHugo pointed out, the file existing doesn't mean the file is ready yet. I have edited the code to handle that! But it still doesn't cover the case where the file already existed, in which case you probably want a dynamic file name like with a timestamp, or you want to delete the file first!

    0 讨论(0)
  • 2021-01-15 19:29

    The ScreenCapture.CaptureScreenshot function is known to have many problems. Here is another one of it.

    Here is a quote from its doc:

    On Android this function returns immediately. The resulting screenshot is available later.

    The iOS behavior is not documented but we can just assume that the behavior is the-same on iOS. Wait for few frames after taking the screenshot before you attempt to read/load it.

    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;
    
    }
    

    Note that you must use StartCoroutine(TakeScreenshot()); to call this function.


    If that did not work, don't use this function at-all. Here is another way to take and save screenshot in 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);
    }
    
    0 讨论(0)
  • 2021-01-15 19:39

    Programmer's code worked successfully by being called like the following. It is designed as coroutine, so it would not interfere frame rate. Hence it should be called as coroutine. Make sure the CallerObject is inheriting from "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);
        }
    }
    
    0 讨论(0)
提交回复
热议问题