Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
7
Question by ThePunisher · Sep 17, 2012 at 09:39 PM · resources.loadloading during runtime

Goods and bads about using Resources.load

Hi guys,

I've had a disagreement with a co-worker for quite a while now about using Resources.load(). Now, I understand how it is used, but I'm trying to get some points on why/when/where to use it. Currently, my co-worker prefers sticking just about everything under the Resources directory. Then loading it during run-time using Resources.load (of course). From my perspective, this is a misuse of the tool.

Can anybody help me understand the implications of using Resources.load better?

This is what I understand:

  • Used for loading assets that are rarely used so that they are not loaded as part of any of the scenes. " For example, there may be a character or other object that can appear in any scene of the game but which will only be used infrequently (this might be a "secret" feature, an error message or a highscore alert, say). ", says Unity.

  • If you want WebPlayers to load a game quickly then you can make a lightweight scene that loads only the minimum required assets, then use Resources.load as needed to load the remaining assets.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

4 Replies

· Add your reply
  • Sort: 
avatar image
7
Best Answer

Answer by whydoidoit · Sep 17, 2012 at 10:30 PM

I agree with your points - well put. If you put it all in Resource directories then it will be included in the build - no matter if you stop using it - normally only assets that are actually being used in a built scene will be included in the actual executable. So putting everything in Resources is a bit of a nightmare because you have to work out whether you are still using things or your executable starts to fill with wasted stuff - big problem on phones.

I use resources for things like:

  • Music - because the player can select a track and I don't want them hanging around when they aren't being used

  • Character animations because I want to load the set that are relevant for the currently selected character.

  • Images that may be displayed at some point during any scene (like control tips etc).

  • Your first point - things that may be loaded but aren't always - like characters that may only be used sometimes.

Prefabs that are always needed in a scene but have no obvious "home" get stuck in a game object that loads with the scene (set using the inspector into public variables- then it is a compile error if I spell it wrong). Generically useful prefabs get loaded in a singleton UsefulPrefabs script where the prefabs are set using the inspector so that I don't have to hunt around in code for them by name (this script is DontDestroyOnLoad and is always included by loading additively from a master scene if it isn't found).

I would much prefer to be able to identify where my objects are so that there is no hunting in code looking for the names being passed to Resources.Load - and as mentioned above - strings are fragile compared to variables.

Comment
Add comment · Show 9 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image ThePunisher · Sep 17, 2012 at 10:41 PM 0
Share

Thank you very much for your input $$anonymous$$ike.

avatar image guavaman · Sep 26, 2012 at 07:01 PM 0
Share

> So putting everything in Resources is a bit of a nightmare because you have to work out whether you are still using things or your executable starts to fill with wasted stuff - big problem on phones.

I'm not sure I understand why this is a problem and why it matters for phones any more than any other platform. It seems to be it would be easier to keep your Resources folder clean than to maintain object lists for every level that may keep changing. If you stop using something permanently, take it out. Or if you're not sure whether you'll be using it or not, move it to a "Unused" subfolder in resources so you can delete it before your final build.

Now for web, you have asset bundles to deal with, so it may be different.

avatar image whydoidoit · Sep 26, 2012 at 07:10 PM 0
Share

Because if you put it in Resources it will be included. If you don't it will only be included if it is used - Unity figures that out for you.

avatar image guavaman · Sep 26, 2012 at 07:26 PM 0
Share

> Because if you put it in Resources it will be included

Included in the build, yes, but not loaded into memory. Why would you have stuff in resources you don't want in the build? Editor tools shouldn't be in there. And for in-progress/undecided stuff, you could have a Work folder inside Resources, but sort and organize when you finalize it. Then before build, you just have to worry about cleaning up Work.

I guess it just depends how you work which way is easier.

avatar image whydoidoit · Sep 26, 2012 at 07:40 PM 1
Share

So per my original point - if you put everything in Resources then it is your job to manage it - this gets big and ugly and misses a key feature of Unity that automatically reduces the size of your build. Which is, as I said, a problem on phones - because phones have a) limited memory b) limited over the air download sizes c) a potential end user cost associated with bandwidth usage.

I don't know about you - but I am continually refining what is included in scenes and as my game development progresses I move from using one set of prefabs to another, one set of textures and models to another etc etc etc.

Given the uses I suggested for Resources I am already having to manage that directory - managing it for things used in my scenes would be a massive pain. I'd rather have a nice little object, that I can set a couple of prefabs into and know that anything it previously had set will be excluded from the build. Plus of course, if I move something, it doesn't break.

Show more comments
avatar image
1

Answer by guavaman · Sep 17, 2012 at 10:56 PM

I generally agree with your coworker, but it depends on your game's needs. (EDIT: Actually, I don't agree that EVERYTHING should go in Resources -- I kind of misread the question. I put all prefabs, audio files, and certain large GUI textures, NOT dependencies like models, animations, textures, etc.) My game is not web-based, so bundling all assets into the build is not a problem. I put most prefabs in Resources because many times objects I want to load are not instantiated in the scene such as bullets, randomized enemies, random objects, etc. I had been instantiating all my objects from a master prefabs object that contained links to all the prefabs in my game, but as you can imagine it started taking up a silly amount of memory as the game grew. I ended up switching to a string-based solution (created with an editor script from my prefabs object each time I change something) which allows me to load the assets as needed from disk with Resources.Load. I use id's to look up prefabs from the lists, but you could also use enums, so there's no dealing with strings in the code. I personally think its far more trouble to manage a prefab list of exactly what objects you want loaded on a per-scene basis because you have to be constantly cleaning up this list for every scene every time you want to add or remove something.

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image ThePunisher · Sep 26, 2012 at 04:37 PM 0
Share

You must be my co-worker, hah. I'm joking. I do agree with you on the fact that linking everything to the scene for the sake of having access to it can cause the scene to get pretty memory intensive. You really only want things that are always available to the player at any given time to be part of the scene. Let's take the bullets for example. You can link the default bullets that the players starts the level with to some game object in the scene. If the player finds a special power-up in the level then you can use Resources.load to get the special bullets assets. What do you think?

avatar image guavaman · Sep 26, 2012 at 06:55 PM 0
Share

> You must be my co-worker, hah. I'm joking.

... I do agree with you on the fact that linking everything to the scene for the sake of having access to it can cause the scene to get pretty memory intensive. :) Well, I was referring to having a gigantic list that holds links to all the prefabs in the entire game, which is what I did at first. That takes a whole lot more memory than a list for one level. $$anonymous$$y gigantic list of linked prefabs stays on disk (never in a scene) and gets turned into a gigantic list of strings (a persistent object in-world) pointing to their location in Resources so I have access to every prefab in the game on all levels, though I certainly won't ever use them all at once. (When adding new objects to my lists, I add them to the giant prefab list on disk and then run an editor script which updates the string list.)
&

gt; You really only want things that are always available to the player at any given time to be part of the scene.

Sort of. Unless you plan on dynamically unloading objects too (like in a sandbox game - Resources.UnloadUnusedAssets), you definitely want to have enough memory available to hold all possible objects that might be instanced in your scene. Linking all the objects in the scene is an easy way to ensure you do, but I find it cumbersome.

If you're not unloading, using Resources.Load is more just for convenience because it prevents you from having to maintain an object list per-level. It doesn't really help with memory in that case and will probably actually complicate things because you have to worry about expanding memory. (I forget if Unity will unload things by itself if needed or not...)

> You can link the default bullets that the players starts the level with to some game object in the scene. If the player finds a special power-up in the level then you can use Resources.load to get the special bullets assets.

Yes, I think that's a good strategy and I had planned doing that in the end when I get to optimization. I currently access everything that needs to be instantiated with Resources.Load, but I think pre-caching some common objects at the beginning of the game/level might help prevent hiccups (which I haven't seen in a desktop build, but just to be safe). I would do it either by linking them to some object in the scene like you said or by having a script instantiate and destroy them on level start.

Obviously phone and web may be different by taking longer to load something on-the-fly, etc. I have no experience with those platforms.

avatar image guavaman · Sep 26, 2012 at 08:15 PM 0
Share

I just clarified in the above post something I may not have made clear. I don't advocate putting EVERYTHING into the resources folder. I don't put models, most textures, animations, other dependencies in there. I mainly have prefabs, audio, and other heavy things like large images used infrequently as part of the GUI. Sorry if I didn't make that clear.

avatar image ThePunisher · Sep 27, 2012 at 05:53 PM 0
Share

I gotcha. Thanks for all the input man. This is exactly the kind of input I was looking for.

avatar image whydoidoit · Sep 27, 2012 at 05:55 PM 0
Share

Just a note - I see the release notes for 3.5.6 mention that they've fixed a memory leak in Resources.Load - that may also explain further some of the issues I have with my files that do sit in that folder.

avatar image
0

Answer by JustinRyder · Oct 05, 2012 at 08:03 PM

(When adding new objects to my lists, I add them to the giant prefab list on disk and then run an editor script which updates the string list.)

Could you give some more info on this system you use? I was thinking of keeping a class with static strings of resource paths. The editor script you described sounds much more convenient.

 class MyResources
 {
     static string
            player = "Prefabs/Player",
            bullet = "Prefabs/Bullet",
            themeSong = "Audio/Main Theme"
            ;
 }
 
 //anywhere i need a resource
 Instantiate(Resources.Load(MyResources.player));
Comment
Add comment · Show 8 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image guavaman · Oct 05, 2012 at 09:34 PM 0
Share

Hi, this Unity answers system doesn't really support huge messages but I'll do my best to post it here. By the way, you should comment, not make a new answer when asking a question. Please excuse any sloppy code. I didn't say it was well written, but it does the job. ;)

// THE PREFAB CLASS - This class is put on a gameobject and saved to a prefab. // This prefab always stays on disk and should never be instanced in a scene. // Drag and drop references to your prefabs in these arrays first. public class Prefabs : $$anonymous$$onoBehaviour { // Prefab arrays public GameObject[] weapons; public GameObject[] bullets; // ... (all your various lists)

 public GameObject GetPrefab(AssetList listName, int index) { // return a prefab
     if(index < 0) return null;
     GameObject[] list = GetGameObjectArray(listName); // get our array by enum
     if(index >= list.Length) return null; // make sure we don't request something out of range
     return list[index]; // return the game object
 }
 
 private GameObject[] GetGameObjectArray(AssetList listName) { // return the right array based on inco$$anonymous$$g enum
     GameObject[] list;

     if(listName == AssetList.weapons) list = weapons;
     else if(listName == AssetList.bullets) list = bullets;
     // ... (all your various lists)
     else list = null;

     return list;
 }
 
 // ... various other helper functions for other things

}

avatar image guavaman · Oct 05, 2012 at 09:35 PM 0
Share

// The Assets class - This class goes on a gameobject. $$anonymous$$ake it into a prefab. // This prefab should be instantiated in the scene and be persistent and not die on level load, etc. // NOTE: I also included a caching system to reduce calls to Resource.Load, but omitted that from this example to make it shorter. public class Assets : $$anonymous$$onoBehaviour {

 // These will be populated from Prefabs by an editor script whenever you add/remove items
 public string[] weapons;
 public string[] bullets;
 // ... (These arrays should mirror those in Prefabs, but are of type string[] ins$$anonymous$$d of GameObject[])
 
 public GameObject GetPrefab(AssetList listName, int index) {
     if(index < 0) return null;
     string[] list = GetStringArray(listName); // get our array
     
     // Try to load object from resources folder
     string fileName = list[index];
     GameObject obj = (GameObject)Resources.Load(fileName, typeof(GameObject)); // load the object
     if(obj == null) {
         Debug.Log("Resources.Load: Prefab not found at path " + fileName + "!");
         return null;
     }
     return obj; // return the game object
 }
 
 private string[] GetStringArray(AssetList listName) {
     string[] list;

     if(listName == AssetList.weapons) list = weapons;
     else if(listName == AssetList.bullets) list = bullets;
     // ...
     else list = null;

     return list;
 }

}

// ENU$$anonymous$$S // $$anonymous$$A$$anonymous$$E SURE enum names match array names EXACTLY public enum AssetList { weapons = 0, bullets = 1 // ... };

avatar image guavaman · Oct 05, 2012 at 09:36 PM 0
Share

// EDITOR SCRIPT class PrefabListEditor$$anonymous$$enu { [$$anonymous$$enuItem ("CustomTools/Update Data/Update prefab string names from prefab lists")] static void Custom$$anonymous$$enu_UpdateStringNamesFromPrefabLists() { string resourcesPath = "Assets/Resources/"; string dataObjectPath = resourcesPath + "Prefabs/DataObjects/"; // This is the path to your prefab with the Prefabs script on it

 // PrefabLists object
 string fileName = "PrefabLists.prefab";
 Prefabs prefabs = (Prefabs)AssetDatabase.LoadAssetAtPath(dataObjectPath + fileName, typeof(Prefabs));
 if(prefabs == null) { Debug.Log("Prefab prefab not found at " + dataObjectPath + fileName); return; }
 
 // PrefabFiles object
 fileName = "Assets.prefab";
 Assets assets = (Assets)AssetDatabase.LoadAssetAtPath(dataObjectPath + fileName, typeof(Assets));
 if(assets == null) { Debug.Log("Assets prefab not found at " + dataObjectPath + fileName); return; }
 
 Custom$$anonymous$$enu_Helper_UpdateFileNamesFromPrefabList(prefabs, assets); // populate string names by taking them from the prefab list object

}

static void Custom$$anonymous$$enu_Helper_UpdateFileNamesFromPrefabList(Prefabs prefabs, Assets assets) { string resourcesPath = "Assets/Resources/"; int updateCount = 0; string[] listNames = System.Enum.GetNames(typeof(AssetList)); int listCount = listNames.Length;

 SerializedObject soSource = new SerializedObject(prefabs);
 SerializedProperty spSource;
 SerializedObject soTarget = new SerializedObject(assets);
 SerializedProperty spTarget;
 
 for(int i = 0; i < listCount; i++) {
   spSource = soSource.FindProperty(listNames[i]);
   spTarget = soTarget.FindProperty(listNames[i]);
   soSource.Update();
   soTarget.Update();
   
   spSource.Next(true); // Array
   spTarget.Next(true); // Array
   spSource.Next(true); // size
   spTarget.Next(true); // size
   
   // Get new array length
   int arrayLength = spSource.intValue;
   
   if(arrayLength != spTarget.intValue) { // arrays are different sizes
     spTarget.intValue = arrayLength; // copy new array length
   }
   
   // Go through each element in the array and copy
   for(int j = 0; j < arrayLength; j++) {
     spSource.Next(true); // element
     spTarget.Next(true); // element
     
     if(spSource.propertyType != SerializedPropertyType.ObjectReference) {
       Debug.Log("Error! Property type " + spSource.propertyType + " not supported! Skipping list!");
       break;
     }
     
     UnityEngine.Object obj = spSource.objectReferenceValue;
     System.Type dataType = obj.GetType();
     
     if(dataType == typeof(GameObject)) {
       spSource.Next(true); // m_FileID
       spSource.Next(true); // m_PathID
     } else if(dataType == typeof(AudioClip)) {
       spSource.Next(true); // m_FileID
       spSource.Next(true); // m_PathID
     } else {
       // Null field or unsupported data type
       spSource.Next(true); // m_FileID
       spSource.Next(true); // m_PathID
     }
     

// CONTINUED NEXT POST

avatar image guavaman · Oct 05, 2012 at 09:36 PM 0
Share

// Save the string // Get a path for each object. These should be in Resources folder, but will find anywhere. string fileLocation = AssetDatabase.GetAssetPath(obj); string filePathAndName = ""; string fileName; string filePath;

     // Format the path to our needs
     if(fileLocation != null && fileLocation != "") { // GetAssetPath returns "" if not found, not null
       filePath = Path.GetDirectoryName(fileLocation) + "/"; // get directory path only
       fileName = Path.GetFileNameWithoutExtension(fileLocation); // strip out file extension
       filePathAndName = filePath + fileName; // combine
       if(filePathAndName.StartsWith(resourcesPath))
         filePathAndName = filePathAndName.Remove(0, resourcesPath.Length); // strip out path of resources folder
       else
         Debug.Log("Error! Object not in resources folder! " + filePathAndName);
     }
     
     spTarget.stringValue = filePathAndName; // save the path string
     
     // Deal with the char array below the string
     spTarget.Next(true); // Array
     spTarget.Next(true); // size
   
     if(filePathAndName != null) { // we had a file path, now skip over the char array
       spTarget.intValue = filePathAndName.Length; // set size of char array
       for(int k = 0; k < filePathAndName.Length; k++) { // just skip over the chars, they'll fill in automatically
         spTarget.Next(true); // char
       }
     }
     
     updateCount++;
   }
   soTarget.Apply$$anonymous$$odifiedProperties();
 }
 Debug.Log("Updated " + updateCount + " prefab names in " + listCount + " lists!");

} }

avatar image guavaman · Oct 05, 2012 at 09:50 PM 0
Share

// About the editor script: // Each time you add/remove items from the Prefabs list on disk, run this editor script // to update the string arrays in Assets. This updates the Assets prefab on disk so any scene with it updates automatically.

// USAGE: // For easier access, get a static link to the Assets object in some static class // so you can call it like this: // Game$$anonymous$$anager.assets.GetPrefab(AssetList.weapons, 5); // Load the weapon at index 5 // // Using arrays like I do makes it a little annoying because they are fixed and you // can't rearrange objects. Also you have to call objects by their ID number. // // Note: $$anonymous$$y version uses strings ins$$anonymous$$d of enums, but I thought using enums would be a little safer, so I modified the code above. I haven't tested the enum version, but it should work.

I suppose it would be easy enough to modify this to create a text file from the Prefabs list ins$$anonymous$$d of storing the path strings in the Assets class as serialized data. Then you could just load in the text file, populate the arrays in Assets from it, and even make Assets a static class (no need for monobehaviour) so you could access it directly. (Why didn't I think of that before... Too much to do. :P )

Show more comments
avatar image
0

Answer by URGr8 · Jul 29, 2018 at 05:25 AM

I know this is an old thread. But Unity will automatically put the stuff in your project that have dependency links into your project folder, like textures or objects that are in a scene.

So really put as little as you need into the Resources folder (to keep the build size down). Only put stuff you will need to load during the game.Like GUIs, sounds, GameObjects that you need to instantiate or use.

If you already have a link to it, like using a GameManager Object with some scripts, then it will get put into the build, so it doesn't matter if it's in the Resources folder or not. But it does make it easier to clean up and change stuff if it's not in the Resources Folder.

You can also look at using Asset Bundles and loading from there if your project is large.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

14 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

prefab loading via resources forced to inactive 2 Answers

Rendering Image Sprites Programatically 0 Answers

How to check the path on Android 0 Answers

Resources.Load returns empty parameters? 1 Answer

Best way use Resources.Load for spcific type? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges