Skip to content

Instantly share code, notes, and snippets.

@tomkail
Last active August 9, 2022 07:48
Show Gist options
  • Save tomkail/e43cffcc3cfea9faefa99316607f9553 to your computer and use it in GitHub Desktop.
Save tomkail/e43cffcc3cfea9faefa99316607f9553 to your computer and use it in GitHub Desktop.
Loads a Sprite, instantly or asynchronously, using Resources.
// Example usage -
// LoadableSprite loadableSprite = new LoadableSprite ("texture");
// loadableSprite.LoadAsync (loadedSprite => {
// Do stuff on load here!
// })
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// You'll need to put this in your scene somewhere so the LoadableSprite class can use coroutines.
public class CoroutineHelper : MonoBehaviour {
public static CoroutineHelper Instance;
void Awake {
Instance = this;
}
}
/// <summary>
/// Loads and manages the loaded state of a sprite.
/// </summary>
[System.Serializable]
public class LoadableSprite {
/// <summary>
/// The Resource relative path.
/// </summary>
public string path;
[SerializeField, DisableAttribute]
Sprite _asset;
public Sprite asset {
get {
return _asset;
} private set {
_asset = value;
}
}
// Note that if the sprite is loaded from another source this won't be updated.
// However, loading it through here afterwards will be instant, since the sprite is already in memory.
[SerializeField, DisableAttribute]
bool _loaded;
public bool loaded {
get {
return _loaded;
} private set {
_loaded = value;
}
}
[SerializeField, DisableAttribute]
bool _loading;
public bool loading {
get {
return _loading;
} private set {
_loading = value;
}
}
public LoadableSprite (string path) {
if(Path.HasExtension(path)) {
this.path = Path.GetFileNameWithoutExtension(path);
Debug.LogWarning("Resources.Load path does not require file extensions. Extension '"+Path.GetExtension(path)+"' has been removed.");
} else {
this.path = path;
}
}
/// <summary>
/// Loads the sprite instantly, waiting until the load is complete. If the sprite is already loaded this should have no performance impact.
/// </summary>
public Sprite Load () {
#if UNITY_EDITOR
if(!Application.isPlaying) {
Sprite editorAsset = Resources.Load<Sprite>(path);
if(editorAsset == null) Debug.LogWarning("Could not load asset at "+path+". Is sprite in the hierarchy of a folder named 'Resources?'");
return editorAsset;
}
#endif
asset = Resources.Load<Sprite>(path);
loaded = asset != null;
if(asset == null) Debug.LogWarning("Could not cast asset "+asset+" at "+path);
return asset;
}
/// <summary>
/// Loads the sprite asyncronously. If the sprite is already loaded this should be instant.
/// </summary>
public void LoadAsync (System.Action<LoadableSprite> whenDone = null) {
CoroutineHelper.Instance.StartCoroutine(LoadCR(whenDone));
}
/// <summary>
/// Loads the sprite asyncronously.
/// </summary>
public IEnumerator LoadCR (System.Action<LoadableSprite> whenDone = null) {
if(loaded || loading) yield break;
loading = true;
float startTime = Time.realtimeSinceStartup;
var request = Resources.LoadAsync<Sprite>(path);
while (!request.isDone) yield return null;
asset = (Sprite)request.asset;
loading = false;
if(request.asset == null) {
Debug.LogWarning("Could not load asset at "+path+". Is sprite in the hierarchy of a folder named 'Resources?'");
} else if(asset == null) {
Debug.LogWarning("Could not cast asset "+asset+" from "+request.asset+" at "+path);
} else {
loaded = true;
Debug.Log("Loading asset "+request.asset+" at "+path+" took "+(Time.realtimeSinceStartup-startTime)+" seconds");
}
if(whenDone != null) whenDone(this);
}
/// <summary>
/// Unloads the sprite instantly.
/// </summary>
public void Unload () {
if(!loaded) return;
if(asset == null) return;
Resources.UnloadAsset(asset.texture);
asset = null;
loaded = false;
}
}
@tomkail
Copy link
Author

tomkail commented Feb 19, 2020

With Unity's Loadables, this is depreciated

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment