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 at work and I don't have unity in this computer so I'll try to recreate it on the fly (there might be some syntax mistakes here and there)
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;
}
As far as I've read, ScreenCapture.CaptureScreenshot is not async so the image should have been written right before I try to load the data, but the problem is as I've said before some times it doesn't work and it loads an 8x8 texture with a red question mark, which apparently is the texture failing to be loaded but the file should've been there so I cannot understand why it's not getting loaded properly.
another thing I've tried (which is disgusting but I'm getting tired of this and running out of ideas) is to put in the update method to wait for some time and then execute the code to load the data and create the texture, sprite and display it but even so, it fails some times, less frequently than before but it still fails, which leads me to belive that even if the file was created it hasn't finish beign written, does anyone know a workaround to this? any advice is appreciated.
As extra information this project is being run in an iOS device.
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".
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
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!
The
ScreenCapture.CaptureScreenshot
function is known to have many problems. Here is another one of it.Here is a quote from its doc:
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.
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: