Lesson learned: How to load resources dynamically at runtime and not loose your sanity on iOS

Even though I tinker and experiment with Unity3d since one year and half, I never crossed path with the necessity of loading assets dynamically at runtime.

At first I fell with the simple approach of System.IO methods that fooled me enough to skip all the documentation about the matter and made all work flawlessly in the editor.

 

SYSTEM.IO methods used:

// check if resource exists
System.IO.File.Exists(fileName)

// custom method to count png in a specified folder
int CountPNGinDirectoryPath(string dirPath){
   string[] totalFiles = System.IO.Directory.GetFiles(path);
   int counter = 0;
   foreach (string item in totalFiles){
      if (item.EndsWith(".png")){
         counter++;
      }
   }
   return counter;
}

 

Nice job!
Lets build it for iOS!
One second later: ERROR
 

Resource folder: why and how does it work

After some research I found out what I was missing:
"Resources"

From Unity's documentation:
The Resources class allows you to find and access Objects including assets.
[...]
All assets in the "Resources" folders will be included in a build.



First you need to create one or multiple folders named exactly "Resources", and place all assets needing manipulation at runtime under that folder (or subfolders).


Keep in mind that you need to use a case sensitive path in your methods and use "/" instead of "\" even if you are on windows, and that the Resources folder will be your root.

You also need to exclude file extension, since the resource will be packed with unity's proprietary format.

For example image.png placed in Background folder under Resources will be called with "Background/image" 



Resource class counterpart methods I used:

 

myTexture = (Texture2D)Resources.Load(resourceString, typeof(Texture2D));
// check if file exists - Resource.Load is null if resource does not exists
if (!myTexture) {
   // create 2d texture to fill the sprite
   myTexture = new Texture2D(1,1);
}

int CountPNGinDirectoryPath(string dirPath){
   int counter = 0;
   Object[] maps = Resources.LoadAll(dirPath);
   counter = maps.Length;
   Resources.UnloadUnusedAssets();
   return counter;
}

Comments