I have an issue with my texture loader, everything works fine but once the function runs Unity freezes until the files are loaded into memory. These two are the functions i use to load the textures and add them to an array.
public void LoadTextureArray(string _dirname)
{
var fileNames = Directory.GetFiles(Application.persistentDataPath + "/" + _dirname + "/", "*.jpg");
source = new Texture2D[fileNames.Length];
Array.Sort(fileNames, (s1, s2) => Path.GetFileName(s1).CompareTo(Path.GetFileName(s2)));
int index = 0;
foreach (var fileName in fileNames)
{
source[index] = LoadTextureFromPath(fileName);
source[index].name = fileName;
index++;
}
}
public Texture2D LoadTextureFromPath(string path)
{
if (string.IsNullOrEmpty(path))
{
Debug.LogError("Texture path is null or empty");
return null;
}
if (!File.Exists(path))
{
Debug.LogError($"File not found: {path}");
return null;
}
byte[] bytes = File.ReadAllBytes(path);
Texture2D texture = new Texture2D(512, 512, TextureFormat.RGB24 , false);
texture.LoadImage(bytes);
Debug.Log("success");
return texture;
}
Now i understand i need to make it async in order for it to work on the background but honestly i have no idea how to proceed, i did read a bit on various forums but most of what i found used WWW and even though i did try some parts i was not successful.
Edit: Ok so for starters i cannot understand which of those two functions i need to make asynchronous. i found a thread which contained this code
Texture2D _content;
Material _material;
// Call this with StartCoroutine(LoadTexture(path));
IEnumerator LoadTexture(string path)
{
// Start the asynchronous load.
var www = new WWW("file://" + path);
// Let the game continue running until the texture has been loaded.
yield return www;
// Replace current content with loaded texture.
if (_content != null)
Destroy(_content);
_content = www.texture;
// Instantiate a copy of the material,
// and hang onto it so we can clean up when finished with it
if (_material == null)
_material = GetComponent<Renderer>().material;
_material.mainTexture = www.texture;
}
void OnDestroy()
{
// Clean up created instances
// (these aren't immediately garbage-collected otherwise)
if(_material != null)
Destroy(_material);
if(_content != null)
Destroy(_content);
}
but i could not make it work by replacing it with this
IEnumerator LoadTexture(string _dirname)
{
var fileNames = Directory.GetFiles(Application.persistentDataPath + "/" + _dirname + "/", "*.jpg");
// Start the asynchronous load.
var www = new WWW(fileNames.ToString());
source = new Texture2D[fileNames.Length];
Array.Sort(fileNames, (s1, s2) => Path.GetFileName(s1).CompareTo(Path.GetFileName(s2)));
//Debug.Log(string.Join("\n", fileNames));
int index = 0;
foreach (var fileName in fileNames)
{
// Let the game continue running until the texture has been loaded.
yield return www;
source[index] = LoadTextureFromPath(fileName);
source[index].name = fileName;
index++;
}
}
and even though this works it still freezes the game abit and it takes more time to load the textures than when the game freezes, maybe i should be making the texture into a asynchronous event but i do not know how to.
Edit: by placing the yield in the foreach loop it seems to be working but is this the way it should be done?
Edit: ok so after some trial and error i think i have gotten to a decent point. this part here works in the way that it loads everything in the background without freezing the game and it loads them as fast as i would like but is it correct?
code is this
private IEnumerator GetTextureFromPath(string _dirname)
{
var fileNames = Directory.GetFiles(Application.persistentDataPath + "/" + _dirname + "/", "*.jpg");
source = new Texture2D[fileNames.Length];
Array.Sort(fileNames, (s1, s2) => Path.GetFileName(s1).CompareTo(Path.GetFileName(s2)));
int index = 0;
foreach (var fileName in fileNames)
{
UnityWebRequest webRequest = UnityWebRequestTexture.GetTexture(fileName);
yield return webRequest.SendWebRequest();
while (!webRequest.isDone)
{
yield return null;
}
Debug.Log("Ends server comm");
if (webRequest.isNetworkError || webRequest.isHttpError)
{
Debug.Log(webRequest.error);
}
else
{
source[index] = ((DownloadHandlerTexture)webRequest.downloadHandler).texture;
source[index].name = fileName;
index++;
}
}
}
```