1
\$\begingroup\$

I have been researching this for 2 days now and I cannot seem to find a proper response. I am trying to figure out a good way to store constant variables within my game.

Basically, does it make more sense to create a singleton script that holds all my prefabs inside it so I can easily access them and instantiate through the game? Or does it make more sense to keep all my assets inside the Resources folder and then call Resources.Load throughout the game (or through a Static class that holds references to all the resource paths and loads the resources on start up)

I have the same question regarding variables used within runtime. Would it be better to run through the Static class that is holding all these prefabs through the Resources folder? Or would it make sense to also hold these values inside the singleton.

Thank you!

\$\endgroup\$
3
  • \$\begingroup\$ Do you have a reason for not simply adding prefab references to the scripts that need them via the Editor? This is quite conventional in Unity. \$\endgroup\$
    – zcabjro
    Nov 18 '16 at 10:27
  • \$\begingroup\$ I have felt that adding the reference points within the scripts is more efficient in case there are anything that breaks the references within the Unity inspector and then manually having to add all the prefabs back into the editor. So by adding const strings that hold paths to the Resources folder holding the prefabs, I can load up all the resources on start up and have statically accessible prefabs \$\endgroup\$ Nov 18 '16 at 15:01
  • \$\begingroup\$ @D34thSt4lker: anything that would break the script references would also break the paths (unless you're frequently doing very naught things like deleting metadata files - if so, stop it) and the paths - unlike script references - don't have a handy debugger for detecting when they break. The Unity references also enable a ton of other very important Unity features regarding asset processing, bundling, preloading, and distribution. You're generally best off using an engine the way it's meant to be used rather than trying to outsmart it. \$\endgroup\$ Dec 20 '16 at 7:51
1
\$\begingroup\$

Although this question is fairly old, it popped up in the feed recently and I thought it might be worth un updated answer.

Basically, does it make more sense to create a singleton script that holds all my prefabs inside it so I can easily access them and instantiate through the game?

If this singleton gets loaded into memory, it will also load all its dependencies, meaning you have all the prefabs in memory at the same time, even if you're using only a few of them.

If your game has the headroom to do this, then it's a convenient way to go. But if you're trying to conserve memory, then this should be avoided.

Or does it make more sense to keep all my assets inside the Resources folder and then call Resources.Load throughout the game

In modern Unity versions, you can use Addressables to get more control over loading and unloading assets at runtime.

You can use AssetReference variables to hold a reference the assets you want to load, without actually loading them until you ask them to load. Then you're not tied to a specific string that might change when you move the asset around or rename it. And the asset can be in the build, in a separate asset bundle, or even downloaded from a remote server, and your consuming code doesn't need to know the difference.

I'd recommend phasing out use of the Resources folder entirely. It's very easy to inadvertently bloat your build with this folder, because every asset inside will always be included in your build, even if nothing ever uses them. Addressables solve all the same problems, better.

I have the same question regarding variables used within runtime. Would it be better to run through the Static class that is holding all these prefabs through the Resources folder?

For this type of thing, I like to use a ScriptableObject

[CreateAssetMenu(fileName="SharedData.asset", menuName="Shared Data")]
public class SharedData : ScriptableObject {

    public Transform someCommonlyUsedPrefab;

    public float someCommonlyUsedValue;

    // ... etc.
}

This will let you right-click in your project folder and create a new asset that acts as a data container whose contents you can edit in the Inspector.

Your other scripts can hold a reference to it the same way they'd reference a prefab, (or you can make a static getter or resource locator to look it up) but you don't need to create a GameObject for it to sit on. It persists between scenes like static data, but unlike static classes or variables, it's easy to use the Inspector to review or edit its current contents.

\$\endgroup\$
1
\$\begingroup\$

Keep it simple. As zcabjro said, the conventional method is to add prefab references to the scripts that need them. If you have a GameObject with a script attached called 'Boy' and he wants access to the prefab called 'ball' to instantiate a game object then write it into his script.

 [SerializeField] private GameObject ball;

 void InstantiateGameObjects()
 {
       GameObject newBall = GameObject.instantiate(ball);
 }

It's unnecessary to hold them all as static objects or singletons throughout the game, just reference them as you need them.

\$\endgroup\$
0
\$\begingroup\$

Half answer to your unclear question. In order to truly understand the Resource.Load you need to consider these points.

  1. 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.
  2. 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
  3. 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. (for more)
\$\endgroup\$
2
  • \$\begingroup\$ Well I'm speaking in terms of like a game where you may have many many playable characters/enemies/items etc. Would it make sense to store all this in the Resources folder and then load up within a central management script that will be accessible by other scripts \$\endgroup\$ Nov 17 '16 at 15:22
  • \$\begingroup\$ While this is all true, it only answers the question about asset loading, not the question about what to do about variables. \$\endgroup\$
    – Philipp
    Dec 17 '16 at 15:06
-2
\$\begingroup\$

You can also use player prefs to store data. This will also carry on between plays, although the downside is that it's a bit slow to access and you can't save loads of data types

//You can get data from player prefs like:
m_Health = PlayerPrefs.GetFloat("Health", 0);
//And set it like:
m_Health = PlayerPrefs.SetFloat("Health",100);
\$\endgroup\$
2
  • 1
    \$\begingroup\$ We like our answers to be more fleshed out. Could you expand on this? \$\endgroup\$
    – Vaillancourt
    Dec 20 '16 at 10:55
  • \$\begingroup\$ I just expanded both answers \$\endgroup\$
    – Kepol
    Dec 20 '16 at 11:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.