I don't understand why loading from Appdata also has a noticeable delay
The delay is not caused just by loading the image file from the user's storage drive; Unity also has to decode the JPG, convert the decoded image into a texture format that can be used by the GPU and then upload that texture into the GPU's memory. The amount of time this takes will depend on the player's hardware and the file size and resolution of the image.
I'd be fine with loading everything at Start in the background, be it from Appdata or from UnityWebRequest before it is visible to the end user. I would like to know how to do that.
We can't give you a precise answer for this if we don't know when the image should be visible to the end user.
If the image(s) should be visible to the user as soon as the scene loads, you might consider loading the image(s) synchronously rather than in the background. To do this, simply call the code that loads the image from a Start()
function in any MonoBehaviour. You might wish to display a loading screen to the user while the image(s) load.
If the image isn't shown to the player immediately, there are various methods you can use to load an image in the background:
You could use File.ReadAllBytesAsync()
instead of File.ReadAllBytes()
, although you'd then need to make sure you synchronized the loaded bytes into Unity's main thread before you called texture.LoadImage()
. However, using this approach, there would still be a delay when you called texture.LoadImage()
as Unity converts the image into a GPU texture format.
On some platforms, you can also use UnityWebRequestTexture.GetTexture()
with the path to the file on the hard drive, using the "file://" protocol (just add "file://" before the image path - for example, "file://c:/folder/image.jpg"). This lets you load the image in the background and monitor its progress with a coroutine. For example:
[SerializeField] private Image image;
[SerializeField] private Transform loadingScreen;
void Start() {
StartCoroutine(LoadImage());
}
IEnumerator LoadImage() {
using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture("file://c:/folder/image.jpg"))
{
yield return uwr.SendWebRequest();
if (uwr.result != UnityWebRequest.Result.Success) {
Debug.Log(uwr.error);
} else {
var texture = DownloadHandlerTexture.GetContent(uwr);
if (texture != null) {
Sprite nSprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
image.sprite = nSprite;
loadingScreen.gameObject.SetActive(false);
}
}
}
}