Is it a bad practice to always instantiate Prefabs from script references? - unity3d

Whenever I need to instantiate prefabs, I always use the following technique
Add a GameObject/MonoBehaviour field to the MonoBehaviour which would instantiate the prefab.
Use this field to instantiate the prefab
E.g.:
public class ExmapleController : Monobehaviour
{
[Serializefield]
GameObject _examplePrefab;
GameObject _exampleObject;
public void SpawnExample()
{
_exampleObject = Instantiate(_examplePrefab);
}
}
Now my problem with this is that first of all I need two references. One for the prefab and one for the instantiated object. Secondly, whenever I need additional prefabs I have to create new and new references inside my script. This sometimes clutters my Scripts and I always wonder that is this memory efficient? What does Unity do behind the scenes? It just only stores a GUID reference for my prefab than somehow loads this prefab based on this reference? Or when I make a prefab reference the whole object tree is pulled into memory and I should rather use Asset bundles or another Unity technique?

Basically that's fine. But if you want to improve your workflow you can try creating ScriptableObjects to store the prefab references and then have only 1 reference to your scriptable object inside the mono behaviour. It will help you keep your mono behaviour classes clear. For more advanced approach you can check Dependency Injection frameworks for Unity. The most common one is Zenject. It helps you in managing dependencies in your classes (prefabs in your case are dependencies of Monobehaviour class).
When you create a reference to a Prefab Unity only store the GUID of the prefab you referenced. It is how resource system in Unity works. But if your prefab is required on the current scene then it will be fully loaded with all inner dependencies. If loading takes much time than it is the reason to think about using Addressables (AssetBundles). Unity doesnt have any other technique to avoid loading the full object tree in memory. But addressables let you control when to load the specific prefab from asset bundles to memory.

Yes this perfectly fine and how it's done. A reference is just that: a reference. The only time a copy of the object is made is when you call Instantiate.
If you have multiple prefabs that are just variations of one you should use ScriptableObject instead and have just 1 prefab that can take any variation form. You would still intantiate them the same way.

Basically that's fine. But if you want to create a huge numbe of objects or delete them you could also have a look at Object Pooling. More infos can be found under the link from the tutorial at Unity:
https://learn.unity.com/tutorial/introduction-to-object-pooling#
"Object Pooling is a great way to optimize your projects and lower the
burden that is placed on the CPU when having to rapidly create and
destroy GameObjects. It is a good practice and design pattern to keep
in mind to help relieve the processing power of the CPU to handle more
important tasks and not become inundated by repetitive create and
destroy calls. (Unity)"

Related

Prefab optimization

We have a MonoBehaviour component holding a long list of prefabs (can be 100).
Those prefabs are meant to be created/destroyed as needed.
The component is singleton getting created on first usage.
The question is related to the memory usage, using a mono behaviour component, I understand this means all the prefabs are being loaded onto the disk when creating the component.
I am looking at a way to limit the loading of those rarely used prefabs.
I thought of having them in different scriptable objects so only the lists from used prefabs would get loaded, with the lists of less common prefabs most likely rarely or never loaded.
I am looking at tips on the topic.

Unity, to what object should I attach my game engine script

Me and my friend are building a simple idle game as our first project in unity.
We got to the point at which we build a script that handles all calculations, and communicates with each GameObject the player sees.
Now, to what should we attach this script?
We would rather not use a GameObject because:
1) The GameObject would be an overkill
2) The GameObject lies in the space where all of my "physical" objects exist (That would be useless since the script does not have to "exist somewhere")
First time posting in stackoverflow, if I made any mistake please tell me ^^
Convention says to put it on the main camera or an empty GameObject.
If you really don't want to do either of those, you could make your class static.
If your class inherits from MonoBehaviour you have to attach it to a GameObject. If you want to attach it to a GameObject it has to inherit from MonoBehaviour.
If you want to better understand the Unity way, I advise you to read up on Entity-Component Systems:
GameObject are Entities
MonoBehaviour are Components
Services and managers generally get implemented as Components in Unity which then get attach to the main camera or to empty GameObjects named after them.
You can create a usual singleton class, and "Game Initializer" monobehaviour, that will initialize all your singletone managers, fabrics, etc...
Just add this monobehaviour to every scene in empty gameobject with a code like that:
if(GameManager.instance == null)
new GameManager();
Or in case of scriptableObjects,
if(GameManager.instance == null)
gameManager.init()
Also, a good desicion is to use Entity System pattern, here is frameworks for unity (Unity-Ash, Entitas, etc)

Instantiate a prefab with a custom base object

Probably know the answer to this already but wanted to run this by the community anyways.
I have a custom object which contains the information I need to feed into a prefab.
I have read somewhere that messing around with contructors on prefabs is a bad idea. Is the best option then to simply pass the intitiatlization info via a method call on the prefab?
Ie: make a script for the prefab that accepts my custom object to configure it? Kind of a best practices question.
That's how I would do it. Basically the prefab needs a reference (not necessarily a separate script) to another prefab with the extra data needed.
Though the question is: why can't this data be in the prefab itself?
If the answer is "because the data is global and there are many prefabs" a good solution to that problem is ScriptableObject, which acts as a global data storage object. A scriptable object has a script and an inspector view like other game objects, and you can assign a reference to the scriptable object to prefabs which can then reference the global data.
Typically ScriptableObject are used for "raw data" or even as a lightweight game database.
Script that creates a ScriptableObject (there are many examples):
http://wiki.unity3d.com/index.php/CreateScriptableObjectAsset
This post explains the SO with a use case and code samples:
http://buchhofer.com/2010/10/unity-toying-with-scriptable-objects/

Unity3D: Instantiating a prefab by its class

In my unity3D project I have a manager script that should take care of initializing a game level, instantiating and placing all relevant prefabs. However, I can't find a way to instantiate a prefab by its class - it turns out that "instantiate" really means something more like "clone" in Unity3D. So as a workaround, I had to make my manager script a MonoBehaviour, attach it to an empty object and assign my prefabs to it from the inspector since it is the only way I have found to make it work at all. This looks kind of awkward. Is there any way to actually instantiate a prefab, without cloning it from a reference?
You can load prefabs at runtime. Just have a look at the script reference which comes with examples:
http://docs.unity3d.com/Documentation/ScriptReference/Resources.Load.html
Here is an article that should clarify how it works:
http://docs.unity3d.com/Documentation/Manual/LoadingResourcesatRuntime.html

Understanding scenes in Unity3d

I have some confusion with scenes in Unity3d and I was not able to find any resources about them.
When should scenes be used? For example in a platformer would every level have to be a different scene? Would the main menu be a scene?
Can one overlay scenes?
How do assets work between scenes? Are they attached to each individual scene and have to be reloaded every time. Can one specify when an asset is no longer needed?
How does one send data between scenes/interface between scenes?
I understand that this is a broad topic, but I didn't want to spam with multiple questions.
When should scenes be used? For example in a platformer would every
level have to be a different scene? Would the main menu be a scene?
There are no general rules about that. In theory you may have just one scene for the whole game.
How you organize your scenes is entirely up to you and often depends on the type of game you are creating.
I think that there are at least 3 features to be considered of using scenes:
they are a logical container for all pre-instantiated objects that might be useful to divide your game into multiple levels/sections.
You can serialize cross references between GameObjects and Components inside a scene (if GO A needs a ref to GO B, and they belong to the same scene, the reference can be serialized and you no longer need to find the referenced object at runtime)
When you load (not in an additive way) another scene, the resources already loaded into memory are automatically released
Can one overlay scenes?
Yes you can using LoadAdditive. Unfortunately, once 2 scenes are both loaded into memory there is no automatic way of distinguish objects belonging to one or the other. So if you load additive a second level environment, it's up to you to keep track of the previous environment and explicitly destroy it if you need to.
How do assets work between scenes? Are they attached to each
individual scene and have to be reloaded every time. Can one specify
when an asset is no longer needed?
As defaults every GameObject of a scene will be destroyed once the new scene is loaded (unless you use an additive scene loading). A way to make a GameObject survive across scenes is to mark it using DontDestroyOnLoad.
If you need to share a particular "configuration" of a GameObject, you can store it as a prefab, and reference it across scenes (but remember that once in a scene it's a prefab instance, so the GO shares with the prefab the initial serialized and not overriden properties, but 2 instances of the same prefab are different objects).
How does one send data between scenes/interface between scenes?
Several ways, depending on what kind of persistent data you want to share.
For a particular GameObject instance let the object survive using DontDestroyOnLoad.
If you have some configuration data that doesn't need to be attached to a specific GameObject you can consider storing a ScriptableObject inside the AssetDatabase and reference it.
If you have data that must persist across different game sessions you can consider storing them into PlayerPrefs.
There are 2 other ways that I don't like, but just to cite them:
Using a static field can sometimes help you in doing that, but it has several problems from my point of view
Save and load from disk (could be useful in several situations, but often it's a platform dependent way and you can have some trouble especially on different mobile platforms)
This is a broad topic btw, I hope this answer can be a quite decent overview.
When should scenes be used? For example in a platformer would every level have to be a different scene? Would the main menu be a scene?
There is no rule as to how many scenes you need to have in your game. However, scenes allow you to logically separate out parts of your game from the rest of it. You have to have a minimum of one scene.
By main menu, if you are referring to a canvas with your UI elements, it will be IN a scene and not a scene itself. Canvas is just another GameObject, that we mostly happen to use for showing game menus. I mostly create a Canvas GameObject, put a script by the name of "UIManager" and put DontDestroyOnLoad on it, so I have access to it in all scenes. Make it Singleton and I ensure that it is not duplicated.
Can one overlay scenes?
Yes, there is no restriction as to how many scenes you can load at a time. What purpose do you plan to overlay scenes though? Maybe there is a better way than loading additively.
How do assets work between scenes? Are they attached to each individual scene and have to be reloaded every time. Can one specify when an asset is no longer needed?
Assets are what you see in your 'project' hierarchy. I think you meant "GameObject"s in the scene, and if so, think of your gameobjects as entities with components (Entity-Component System). All entities in a scene get destroyed when its parent scene is destroyed until explicitly stated not to, using DontDestroyOnLoad in some component (a monobehavior in case of unity). The destroyed ones will get garbage collected.
So how they are loaded (or reloaded) depends on your implementation, on whether you are instantiating/destroying them time an again or if you put their instantiated prefabs in a cached object and retrieving later from it.
How does one send data between scenes/interface between scenes?
Heisen covered the ones I could think of. Just to add a little bit to it, it also depends on how you want to the architect your project. So if you had an underlying data structure to e.g. hold Commands, you are free to use it in any part of your project
Most games would be organised to have scenes for every level(including the main menu) but that is entirely up to you.
You can use the data from one scene to another if you save it in a text file or binary. There are a lot of tutorials on how to do this. I find documentation helps a lot.
Assets are universal in a project.
You can not overlay scenes.
When should scenes be used? For example in a platformer would every level have to be a different scene? Would the main menu be a scene?
When to use a scene is up to you. If you are just starting I would recommend using a different scene for each section of your game.
Can one overlay scenes?
Yes, using LoadSceneMode.Additive(). (LoadAdditive() is obsolete)
How do assets work between scenes? Are they attached to each individual scene and have to be reloaded every time. Can one specify when an asset is no longer needed?
By default, assets are deleted when using SceneManager.LoadScene(). However, if you use DontDestroyOnLoad(), the object will not be destroyed when entering new scenes. If you want to only keep an object through a few scenes instead of all, use Destroy() with some boolean logic.
How does one send data between scenes/interface between scenes? I understand that this is a broad topic, but I didn't want to spam with multiple questions.
You can send data through scenes by using the aforementioned DontDestroyOnLoad(), referencing the data on different scripts, using ScriptableObjects, using JSON Serialization, using StreamWriter(), using PlayerPrefs (Don't use for important information), the list goes on. I would personally recommend using ScriptableObjects for their accessibility, and StreamWriter() for it's encryption capabilities.