Using Resources Folder in Unity

Using Resources Folder in Unity

You can't read the Resources directory with the StreamReader or the File class. You must use Resources.Load.

1.The path is relative to any Resources folder inside the Assets folder of your project.

2.Do not include the file extension names such as .txt, .png, .mp3 in the path parameter.

3.Use forward slashes instead of back slashes when you have another folder inside the Resources folder. backslashes won't work.

Text files:

TextAsset txtAsset = (TextAsset)Resources.Load("textfile", typeof(TextAsset));
string tileFile = txtAsset.text;

Supported TextAsset formats:

txt .html .htm .xml .bytes .json .csv .yaml .fnt

Sound files:

AudioClip audio = Resources.Load("soundFile", typeof(AudioClip)) as AudioClip;

Image files:

Texture2D texture = Resources.Load("textureFile", typeof(Texture2D)) as Texture2D;

Sprites - Single:

Image with Texture Type set to Sprite (2D and UI) and

Image with Sprite Mode set to Single.

Sprite sprite = Resources.Load("spriteFile", typeof(Sprite)) as Sprite;

Sprites - Multiple:

Image with Texture Type set to Sprite (2D and UI) and

Image with Sprite Mode set to Multiple.

Sprite[] sprite = Resources.LoadAll<Sprite>("spriteFile") as Sprite[];

Video files (Unity >= 5.6):

VideoClip video = Resources.Load("videoFile", typeof(VideoClip)) as VideoClip;

GameObject Prefab:

GameObject prefab = Resources.Load("shipPrefab", typeof(GameObject)) as GameObject;

3D Mesh (such as FBX files)

Mesh model = Resources.Load("yourModelFileName", typeof(Mesh)) as Mesh;

3D Mesh (from GameObject Prefab)

MeshFilter modelFromGameObject = Resources.Load("yourGameObject", typeof(MeshFilter)) as MeshFilter;
Mesh loadedMesh = modelFromGameObject.sharedMesh; //Or design.mesh

3D Model (as GameObject)

GameObject loadedObj = Resources.Load("yourGameObject") as GameObject;
//MeshFilter meshFilter = loadedObj.GetComponent<MeshFilter>();
//Mesh loadedMesh = meshFilter.sharedMesh;

GameObject object1 = Instantiate(loadedObj) as GameObject;

Accessing files in a sub-folder:

For example, if you have a shoot.mp3 file which is in a sub-folder called "Sound" that is placed in the Resources folder, you use the forward slash:

AudioClip audio = Resources.Load("Sound/shoot", typeof(AudioClip)) as AudioClip;

Asynchronous Loading:

IEnumerator loadFromResourcesFolder()
{
//Request data to be loaded
ResourceRequest loadAsync = Resources.LoadAsync("shipPrefab", typeof(GameObject));

//Wait till we are done loading
while (!loadAsync.isDone)
{
Debug.Log("Load Progress: " + loadAsync.progress);
yield return null;
}

//Get the loaded data
GameObject prefab = loadAsync.asset as GameObject;
}

To use: StartCoroutine(loadFromResourcesFolder());

Searching through all subfolders when using Resources.Load in Unity

There is no way to change the Resouces.Load() static method functionality, it's Unity Internal. However, you can write your own custom class that does your desired functionality. The code needs to find all the directories inside the Resources folder and search for the file. Let's call the class ResourcesExtension

public class ResourcesExtension
{
public static string ResourcesPath = Application.dataPath+"/Resources";

public static UnityEngine.Object Load(string resourceName, System.Type systemTypeInstance)
{
string[] directories = Directory.GetDirectories(ResourcesPath,"*",SearchOption.AllDirectories);
foreach (var item in directories)
{
string itemPath = item.Substring(ResourcesPath.Length+1);
UnityEngine.Object result = Resources.Load(itemPath+"\\"+resourceName,systemTypeInstance);
if(result!=null)
return result;
}
return null;
}
}

Then all you need to do is calling the static method.

ResourcesExtension.Load("image", typeof(Texture2D))

adding a path to the resources folder in Unity

Regarding your first question Resource.LoadAssetAtPath has been deprecated and removed but as noted in the documentation you can use AssetDatabase.LoadAssetAtPath instead: https://docs.unity3d.com/ScriptReference/AssetDatabase.LoadAssetAtPath.html

So to load a resource using the path your can do:

Texture2D t = (Texture2D)AssetDatabase.LoadAssetAtPath("Assets/Textures/texture.jpg", typeof(Texture2D));

Regarding your second question, I don't see any reliability problem in using the resources folder to store any asset you want to reference using Resources.Load.

Playing AudioClip fetched from Resources folder

  1. Unity does not support loading mp3 at runtime.
  2. Unity does not recommend using the Resources folder:

Don't use it.

This strong recommendation is made for several reasons:

  • Use of the Resources folder makes fine-grained memory management more
    difficult Improper use of Resources folders will increase application
    startup time and the length of builds
  • As the number of Resources
    folders increases, management of the Assets within those folders
    becomes very difficult
  • The Resources system degrades a project's
    ability to deliver custom content to specific platforms and
    eliminates the possibility of incremental content upgrades
    AssetBundle Variants are Unity's primary tool for adjusting content
    on a per-device basis

Check this answer for a solution how to load audio files:

public void LoadSong()
{
StartCoroutine(LoadSongCoroutine());
}

IEnumerator LoadSongCoroutine()
{
string url = string.Format("file://{0}", path);
WWW www = new WWW(url);
yield return www;

song.clip = www.GetAudioClip(false, false);
songName = song.clip.name;
length = song.clip.length;
}

Importing each line from text file from Resources in Unity to list in C#

To begin with Don't use Reources!

If against Unity's own recommendation you still want to do it for some reason then you have to load that resource using Resources.Load in your case as a TextAsset like e.g.

// assuming your path is e.g. "Assets/Resources/Text/AllWords.txt"
var file = Resources.Load<TextAsset>("Text/AllWords");
var content = file.text;
var AllWords = content.Split("\n");
listOfWords = new List<string>(AllWords);

The better approach though would probably be to listen to what Unity recommends and instead of using Resources at all rather place your file into the Assets/StreamingAssets folder and access it later via Application.streamingAssetsPath

either using as you did

string[] AllWords = File.ReadAllLines(Path.Combine(Application.streamingAssetsPath, "AllWords.txt");
listOfWords = new List<string>(AllWords);

Or - depending on the platform, e.g. in Android you can't directly access the StreamingAssets

StartCoroutine(LoadWords());

...

private IEnumerator GetRequest()
{
var url = Path.Combine(Application.streamingAssetsPath, "AllWords.txt");
using (var webRequest = UnityWebRequest.Get(url))
{
// Request and wait for result
yield return webRequest.SendWebRequest();

switch (webRequest.result)
{
case UnityWebRequest.Result.Success:
var content = webRequest.downloadHandler.text;
var AllWords = content.Split("\n");
listOfWords = new List<string>(AllWords);
break;

default:
Debug.LogError($"Failed loading file \"{url}\" - {webRequest.error}", this);
break;
}
}
}

You could actually also simply put your file into a "normal" folder like Assets/AllWords.txt and then directly reference it via the Inspector in a

public TextAsset file;

or

[SerializeField] private TextAsset file;

and then access the content via

var content = file.text;
var AllWords = content.Split("\n");
listOfWords = new List<string>(AllWords);

Unity load files from outside of resources folder

You can't load TextAsset from an external path(path not in the Unity game). In fact, you can't even load it from a path in the project itself which is not the Resources path which is then loaded with the Resources API.

One option you have is to use the AssetBundle. Add the TextAsset to the Assetbundle then you can load the Assetbundle from any path and extract the TextAsset from it.

If you just want to load any file outside the Unity path, you can do this without TextAsset. Just use any of the System.IO API such as File.ReadAllText an File.ReadAllBytes. This should be able to load your file.



Related Topics



Leave a reply



Submit