Instantiate a prefab with a custom base object - unity3d

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/

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

Find object from another scene

I need to find an object from another scene. I have checked both Find and FindWithTag, but both of them give me this error:
NullReferenceException: Object reference not set to an instance of an object.
As i know - there is no way to find object on other scene.
First idea - you can load it as additive scene using SceneManager.LoadScene("OtherSceneName", LoadSceneMode.Additive);
and then use Find
You may find more info here: https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager.LoadScene.html
You can write a Game Manager, which can make a script/object that will persist between different scenes, allowing you to carry variables between them. You could use it to have the button change a variable, then have the other scene check the variable when it loads to change the sprite.
A Unity tutorial is here:
https://unity3d.com/learn/tutorials/projects/2d-roguelike-tutorial/writing-game-manager
In your specific case, I'd use PlayerPrefs.Save/SetString to save the variables when player interacts with your UIs or Game Objects in Scene A.
Then when you loading your Scene B, write a scene manager script and on its Awake(), use PlayerPrefs.GetString to retrieve variables, and change your game object behaviors based on the loaded variables.

Save/Load scene state for NPC actors

All of the examples that I've seen of saving/loading a scene in Unity are either only saving/loading simple data (like the player's current health and position), or they're using a purchasable asset from the Unity store. The logic I need is a little more complex than having just a few predefined character parameters to save, and I'd rather learn the proper way to do this instead of buying a Unity store asset, so I'm asking here.
My scenes have some actors (NPCs and enemies) that are defined in the scene in the Unity editor, and some actors that are dynamically added via script during run-time. When the player saves, I want to record the current position/state/etc. of each actor, and then restore those actors to their last states when the player loads the game.
For the actors that defined in the Unity scene in the editor, I'll have to be able to look up the corresponding actor's data within my persisted data, and reapply that state to the actor. One of my main struggles here is being able to identify which set of data goes to which actor, since the actors in the Unity scene often just have generic names (like goblin) so there's no way to tell instance A from instance B. I thought about doing something like creating a PersistentData object that I can assign to each actor, and have the PersistentData object generate unique GUIDs for each actor. But for something as common as saving/loading scene state, I don't want to write a bunch of custom logic if there's already something built in that'll do what I want.
The second problem I'm having is that for actors that were dynamically added to the scene, I'll have to write some code to recreate them after loading the scene. Again, if there's already a built-in or accepted way of doing this, I don't want to write a bunch of code and reinvent a bad facsimile of an existing wheel.
My actors are all derived from MonoBehaviour, so I can't serialize them directly.
Is there an existing way within Unity to do this, or is there a commonly accepted way of handing this scenario?

Would it be possible to change the parent of an instanced object in unity?

Would it be possible to change the parent of an instanced object in unity?
Generally my thought is that it would be just the same as any other GameObject.
myObject.transform.SetParent(newParentObject.transform);
But I thought there may be special rules for cloned objects because you set the parent in creation of the instance object. Do they have rules (what are they) or is it the same?
Yes, you can. It is the same code. (Just asked an old friend) so if someone needs to know:
myObject.transform.SetParent(newParentObject.transform);

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