- Home /
Loading multiple textures from the files ystem and using them as textures.
Hello
I'm trying to figure out how to load a lot of small pngs from the file system without consuming all the available RAM.
The images will be used in at least two ways:
Character creation screen, where the player can change the clothing, face & body. With multiple characters visible at the same time that can be edited.
NPC generation, taking the textures from the list and displaying them on a prefab via RawImages
The problem:
Currently, I'm trying to load 10,915 images with most of them being 1kb, while the biggest ones are around 3kb. All images considered, it's about 311 MB worth of disk space.
I've tried using WWW, UnityWebRequestTexture and File.ReadAllBytes but all of them yield similar results.
Loading all the images at the start of a scene, the memory usage balloons to around 4gb, and using Unity's profiler, about 3.5gb are used by the textures.
My, question is, how do i go from 311MB in disk to over 10x the memory usage at 3.5gb in RAM and Is there a way to optimize this?
This is the code I'm using to load and test them.
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;
public class ImageTest : MonoBehaviour
{
// Testing elements
public RawImage image; // Where to display the images
public float updatePawnsEverySecs = 5.0f; // How long between updates
private float _timeLeft = 0f; // How long before we have to update the texture
// Stores the images for later use
private List<Texture2D> _texture2Ds = new List<Texture2D>();
private void Update()
{
if (_timeLeft <= Time.deltaTime)
{
// Time's up! Update the pawn
image.texture = _texture2Ds[Random.Range(0, _texture2Ds.Count)];
// Reset the timer
_timeLeft = updatePawnsEverySecs;
Debug.Log("Updated texture");
}
else
{
// update the timer
_timeLeft -= Time.deltaTime;
}
}
private void Awake()
{
int _totalImages = 10915; // Number of images in the folder for testing purposes
string path = "E:/Unity/Projects/CharacterCreation/Data/Img/"; // The path were the images are stored
// Load all images into memory
for (int i = 0; i < _totalImages; ++i)
{
Texture2D tex2d = LoadTexture(path + i + ".png"); // Image names are in the form of 0.png, 1.png, 2.png up to 10915.png
if (tex2d == null)
{
Debug.Log("No texture loaded");
}
else
{
_texture2Ds.Add(tex2d);
//Destroy(tex2d); // This lines makes it so that the memory is freed, but the textures are also null
}
}
}
// Taken from: https://forum.unity.com/threads/generating-sprites-dynamically-from-png-or-jpeg-files-in-c.343735/#post-4068442
public Texture2D LoadTexture(string filePath)
{
// Load a PNG or JPG file from disk to a Texture2D
// Returns null if load fails
if (File.Exists(filePath))
{
var fileData = File.ReadAllBytes(filePath);
var tex2D = new Texture2D(2, 2);
if (tex2D.LoadImage(fileData)) // Load the imagedata into the texture (size is set automatically)
return tex2D; // If data = readable -> return texture
}
return null; // Return null if load failed
}
}
I'm skipping Unity's resources and assets since this images should come from mods and putting a couple of images inside a folder is far easier.