Unity's new "Prefab Variant" feature, introduced in 2018.3, is pretty sweet; you can learn more about it here.
I made some changes to an imported 3D model, preparing it for usage in my game, and then dragged the changed GameObject into the file area to save the prefab, when I was asked whether to save it as an original prefab or a prefab variant.
The first (original prefab) option basically removes ties to the source prefab (the 3D model), applying all overrides and setting it in stone. The latter (prefab variant) option still uses the 3D model prefab as it's imported, and applies all of the changes I've made as overrides atop that, meaning if I re-import the model, its new changes will propagate and the changes I'd made on the prefab variant would also still exist.
That sounds great! In fact, I can't think of any circumstance where I wouldn't want that. If I was changing the source prefab so much that the overrides became invalidated, then I'd need to redo work whether or not I used the prefab variant feature - no difference there.
Thus I can only think of benefits to using the prefab variant... Perhaps it's an overhead thing, but I don't know anything about that. I even get the feeling that there could be some performance benefits to using variants (deduplication of prefabs or something like that), but that's me just speculating.
Hence my question: when and why shouldn't I use the new prefab variant feature, and opt for original prefabs instead?
Variants are great if you want several versions of the same base object. if you have more than one type of the same object you should always use them. the overhead is practically the same, but its a great orginizational feature! since its mainly to improve ease of use, for multiple objects as well as workflow, there is a major caveat to using it.
Dont use this feature if your disorganized. but wait, your going to use it, its just to great, having all those different prefabs ready at a moments notice! so heres the thing...
if your making a new version of your base object, replace the base object... you dont want some to be a variant of the bas, and others the variant of a variant, keep it organized, and you will reap the rewards in the time-management are of your project!
Related
I have four different Canvas elements in my Unity scene. This organizes them by concern, but also improves performance since I don't have to rebuild all the elements if I "dirty" one of them. I want to create prefabs of each so I can reuse them across the game, and also so there are less elements in my scene file (I have yet to figure out why Unity doesn't re-organize YAML to match the scene order and hierarchy. Currently I can see no reason and it makes source control a huge pain).
So, my question: Should I include the Canvas as the parent GameObject in the prefab, or should I make the first child the prefab (see image)? I see two perspectives:
On one hand it's nice to scan the list of elements in the root of the scene and see the blue objects and know they are automatically replicated across scenes. Plus, the more object stored in the prefab then there will be less to pollute my YAML file.
On the other, with a Canvas Scalar script on the parent, the sizes inside the prefab are going to be updated every time I change the resolution / platform and I've read it's not good always update them outside of prefab mode. The other issue is the fact that UI elements usually have a lot of external references to update text and so forth.
After a lot more research I've come to some conclusions about the answer:
As stated in this talk at Unite 2017, isolating UI element "islands" by concern AND how often they are updated will keep the UI from affecting performance. The video also states it is fine to use multiple Canvases inside other Canvases to achieve this goal.
If you add a prefab whose values are updated from outside the prefab they will appear as "overrides" to that prefab. This includes if you link to elements outside the prefab from within it and vice versa (see image). Importantly, it is not possible to apply these overrides to the prefab, and that's kind of the point. Unity accepts that these changes will happen and this is how it deals with them without breaking the prefab or the scene.
So the answer is yes, it's no problem to include the Canvas parent in the prefab, and you can even organize it inside other Canvas so they all inherit the same settings. Further, since the more code stored in prefabs decreases the extra (unorganized) identical code in the .unity YAML file (in my case from 17,000 lines to just less than 5000!) then this is the recommended way.
I am new to Unity and I'd like to know what's the best way to add a script to a Prefab.
I currently see two ways of doing so:
1) Use the Unity interface to add it to an existing prefab
2) Use the AddComponent following the code which instantiates the prefab
I try using the 2) everywhere as I am using git to source control my code and I think conflicts may be easier to resolve inside code (compare to inside .prefab files by instance). But I may be wrong.
Is there any unity good practice regarding this ?
That's indeed the only two ways to add a component to a GameObject.
The primary way you are expected to add components to GameObjects is the Unity interface. Being able to setup logic and data through the interface rather than code is one of the big benefits of using such a game engine. It gives you flexibility and it smooths the process for quite a number of operations.
AddComponent use leans more toward adding a component to change the behavior of an existing GameObject or to create a GameObject from scratch, both at runtime. Most people usually don't make an use of it.
Git handles .prefab merging just fine. These are basically just text files with tags and structure so that it can be interpreted by the engine and be readable for an user (think of XML files).
I made a script that copy all materials from a gameobject to another. It 'a script that runs in the editor to press a button.
TargetComponents[j].gameObject.transform.GetComponent<Renderer>().material=ComponentsToAdd[i].gameObject.transform.GetComponent<Renderer>().materials;
Is a Unity 5 script, but would be the same in unity 4, it makes little difference, like:
TargetComponents[j].gameObject.transform.render.materials=ComponentsToAdd[i].gameObject.transform.render.materials;
Works but the materials that I copied are not the same but are instances.
I would like to know how to tell him not to create instances but use their original materials in asset.
Is possible?
Unity offers two ways to get at a renderer's materials:
The sharedMaterial property will return the original material asset. That's what you want, here.
The material property will internally copy the shared material, assign it to the renderer, and returns the new copy. That's usually the "safe" thing to do, especially for less experienced developers who may not understand the distinction, but it's almost never the right move for editor scripting.
Renderers also expose materials and sharedMaterials arrays, in case you have multiple materials on one object.
You probably already know this, but be careful editing the shared material, as it is shared between all renderers and assets which reference that material.
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.
I have a "design pattern" problem. I want to enable for a player to change his state. Lets say I have three states or super powers if you will. Each of them have different abilities. If this abilities were just based on some attributes (lets say mass or speed) I could just change that on the player and everything would work fine.
But what if there are some other functionalities changed. Lets say if the player is in the state 2 and he jumps the animation is different and some other thing changes. Now I know I could make this with a lot of checking in update loop for states but I want to make this elegant.
My idea until now is to make generalPlayer object and the each special player inherits from it and adds special abilities, and when player change state I would kind of change instance of player to that instance.
Is there any better way? I am using c# as scripting language
The problem I have with that approach is that you are using multiple different objects for one player. There could be some mess involved with passing data every time the player changes states which would be better avoided. Since C# has delegates, which, for our purposes, behave much like first class functions, it is possible to change the behavior of your player by changing out certain routines and field values on every change of state. This allows you to keep your data in one object and change behavior on the fly without relying solely on conditionals. There is a pithy phrase I have heard many times, that an object encapsulates state and behavior. In C#, you can change state by manipulating field values, and change behavior by relying on delegates. That should cover your problem.
I have found the best suiting sollution thanks to friend. What I use was an Strategy pattern and then put different instances to the interface I used to controll the player. It works like charm. Thanks all for help.