- Home /
How do I get a list of filenames in a Resources folder?
Hello!
I have my level data stored in Unity/Assets/Resources/Levels
I can do Resources.LoadAll()
to load everything from this folder, but that seems heavy-handed. I just want a list of filenames, so I know which files I can use Resources.Load()
to load later.
How can I check if a file exists without loading the whole file?
Thanks for reading this!
Answer by bfowle · May 20, 2013 at 07:22 PM
This can be achieved via native C# (`System.IO`):
FileInfo[] fileInfo = levelDirectoryPath.GetFiles("*.*", SearchOption.AllDirectories);
foreach (FileInfo file in fileInfo) {
// file name check
if (file.Name == "something") {
...
}
// file extension check
if (file.Extension == ".ext") {
...
}
// etc.
}
You can filter out certain files and/or extensions based on the pattern in GetFiles() this example is checking all files in this dir.
Checking for a file existence is done w/the same library:
if (File.Exists("/path/to/file.ext")) {}
Thanks for the response. I added a line to the beginning DirectoryInfo levelDirectoryPath = new DirectoryInfo(Application.dataPath);
and the code works great in Unity Editor.
However this does not work on all platforms. On iOS, there does not appear to be a Resources directory under Application.dataPath
. It appears Unity packs the entire resources directory into a single file /var/mobile/Applications/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX/[name].app/Data/resources.assets
so FileInfo does not work in this case.
Ahh yes. I believe there is a workaround for this iOS case on this forum post.
It seems like I can actually get files in Assets/Strea$$anonymous$$gAssets
through FileInfo
, but Assets/Resources
is still unavailable since it is not actually a directory on device.
So it seems like the two workarounds I have so far are to either put my files in Strea$$anonymous$$gAssets
or check if Resources.Load()
returns a null value.
$$anonymous$$ind of a cheesy workaround, but could you generate a directory listing at build time and load it as a text asset?
yoyo, yes that is totally a valid workaround! I assume if I wanted to take that route then the BuildPipeline class is what I would use.
Answer by Eric5h5 · May 21, 2013 at 08:30 AM
There is no Resources folder on any platform (and therefore no filenames); everything in Resources is compiled into a file called resources.assets.
This is .... taking the context after being compiled, Obviously the user in a round about way without knowing is asking.. How can i refer to the memory allocation of compiled resources using their filenames as allocation points
Answer by astracat111 · Feb 23, 2018 at 10:25 AM
What you REALLY need to do is to put the resources you need to load inside your persistentDataPath folder UPON THE GAME STARTING. You can't use dataPath with all platforms, you can't use File.IO, so you will have to use Application.persistentDataPath.
I ran in to this problem recently with many of my files for my game. To get it working on Android platforms as well, I end up needing to take my files, put them in my SteamingAssets folder, then from there extract them to my dataPath folder. I use a library called SharpZip for this and use .tgz files (they're like .zip files but for Linux so I can get all this working on android). I create the .tgz file at start as a copy of the StreamingAssets path (which isn't accessible on android upon build as it's packaged into like a .apk).
I then extract that .tgz file into the persistentDataPath, esentially recreating my streamingAssets folder but at persistentDataPath at runtime. You have to check of course if there are already files there upon runtime as well so you don't overwrite your data files the second time you run the game.
PersistentDataPath is that path that you can access as a directory upon runtime on many different platforms including iOS, Android, Mac etc... Again, you can do this also with StreamingAssetsPath but it won't work on certain platforms.
Another quick tip: Make sure that you delete the files you need to with void OnApplicationExit() or whatever that method is.
I think that should be an accepted answer, with a sample code and images would make this answer better.
That's not really a solution, at least not a nice one. Unity can only load some assets from external sources. For example Unity can only load png or jpg at runtime dynamically. $$anonymous$$odels can't be loaded at all (not natively). persistentDataPath is just a storage location for data your game generates that should persist. Assets that are already shipped with your game shouldn't be "unpacked" into folder. This may apply when downloading AssetBundles from a server but not for normal assets.
As i said some assets can't actually be loaded. So they need to be imported in the editor and either shipped with your application or loaded on demand using AssetBundles.
Creatnig and deleting many larger files in the persistent data path that's not really necessary is a bad practise. For all mobile users that just means you use up the write cycles of the flash memory.
The next thing is if you ship the assets with your application, how do you actually access them in the first place in order to store them in the persistent data path?
Yes, using an archive would work but isn't really necessary since a build on mobile is already compressed.
I've actually posted a solution in my answer here. I've written the resourceDB several years ago which creates a list of all files in the resources folder(s) at edit time and stores that information for runtime use. The resources folder allows you to include any kind of asset. $$anonymous$$odels, textures, animations, prefabs, audioclips, ...
Great answer. and the "stea$$anonymous$$g" assets typo cracked me up
Answer by Bunny83 · Feb 23, 2018 at 11:06 AM
Just for completeness I've created a "resource DB" two years ago which allows you to store all file information of assets inside resources folders in a "database" (ScriptableObject) which allows you to use that information at runtime. It only requires a "manual" update of the DB by selecting "Tools/Update ResourceDB". It will automatically create a scriptable object inside Assets/Resources/
and fill it with all the path information about all resources in any resources folder
Answer by Zexx500 · Aug 13, 2021 at 03:29 PM
What really bothers me is that all those workarounds people have created took so much effort and experimentation, testing on various platforms, different solutions for different platforms........ instead of Unity just providing us with one function:
Resources.ListAll()
That's all. A resource file most likely already contains a listing of its content (otherwise how would LoadAll work) so all they have to do is to EXPORT the damn function. The same function that LoadAll uses to find all the objects in Resources. Just return us their names, instead of loading them all.
Unity, please export the damn function. It makes no sense that we have to do all these workarounds when the best solution is already there, just hidden from us. Write the word "public" in front of it.
This does not answer the question. UA is not monitored by Unity staff and not a place for feature requests. Also you just necro posted without adding anything useful to this question. Your "invented" ListAll method will most likely confuse people who come across this question.
Finally we don't know how the internal database is structured. It may just contain hash codes of assets, even though they remember which assets are under which "folder", does not necessarily mean the full path information is remembered at all. The Resources folder works like this for 10+ years now, so it's extremely unlikely they will change anything here.
ps: The source code of the managed part of the Unity API is available for reference. So no, there doesn't exist any such method yet. We don't know how the C++ part looks like.
Okay, it's not an answer, but the function must exist, because the LoadAll function works somehow, doesn't it? So, whichever method it uses to find resources and load them, can be used to just get their names. But they didn't give that function to us, did they? That's a $$anonymous$$or change in code for them, a huge gain for us. And the reason why the function wasn't exported is because nobody asked for it.
If I was using Unity 7 years ago, that would certainly be one of my feature requests. But nobody asked. Seems to me that Unity community is equally submissive like most of communities, which is why things advance in the wrong direction. Unity gets more chaotic every day. It's not only that project managers are without ideas, but the community itself is without ideas or suggestions.