Unity3D: Instantiating a prefab by its class - unity3d

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

Related

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

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)"

Unity : Destroy a GameObject that is part of a prefab

The console shows me this error :
Cannot destroy GameObject that is part of a prefab instance. UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)
I'm confused. The Logs don't tell which prefab or GameObject is involved.
Can u help me ?
Thanks a lot for answers !
Many times when you edit prefabs you will notice that some of them can be blue, while others are with no color. The blue means that they maintain the reference to the original prefab in the project and that they are not a copy, so any change made to them wil be done to the original prefab itself, so the original prebab from which the copies (clones) are made from.
To avoid this, you need to unpack the prefabs, so that you manipulate the copy instead of the original reference.
Probably the error is due to the fact that you are destroying some prefab that is not unpacked, so not destroyable by the runtime GameObject.Destroy that is to destroy a cloned copy from the scene.
Looks like you trying to destroy part of the prefab that is not instanced to the scene. If you need to modify some prefab in editor scripts please refer to PrefabUtility but be aware that this class is accessible only from UnityEditor.
Otherwise please double check your code maybe you using the wrong reference to object after prefab instantiation.
Had this issue recently. A nested prefab was missing in one of the prefabs. Happened when an old prefab was deleted. Check your scene for "Missing Prefab"

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/

UnassignedReferenceException: Event after assigning?

I'm an experienced programmer learning Unity for the first time. I know this is the most basic and common error for the newbies. I think I have got it right but it still produces this error. What am I doing wrong?
UnassignedReferenceException: The variable player of 'GameManager' has not been assigned. You probably need to assign the player variable of the GameManager script in the inspector.
I think the following screenshot provides everything needed.
you have to assign Game Asset in the hierarchy panel to the game object which has GameManager.cs Script Component
I too am new to Unity and had a similar problem, but after thinking about what was going on I came to the conclusion that the error message was misleading me a bit. When it tried to be helpful by suggesting "You probably need to assign the player variable of the GameManager script in the inspector" I went straight to the script and set it but the error persisted.
It was then that I realised that I didn't have an object in the Hierarchy panal which had my script attached. What I was doing was instantiating an object (my 'player' prefab) at runtime and it was the prefab that had the script attached. Of course, my script might be added to any number of objects and each object will have its own variables, so each object needs to have its own instances of its variables set. If you wanted the same value to be set in all instances you probably make your variable static but it won't then appear in the inspector. So, setting the variable in the Script component of my prefab fixed it for me.
I think that's enough waffle for one day - hope it helps somebody! :)