- Hands-On Unity 2020 Game Development
- Nicolas Alejandro Borromeo
- 1564字
- 2025-02-25 01:46:22
Prefabs
In the previous example, we created lots of copies of our enemy around the scene, but in doing so, we have created a new problem. Let's imagine we need to change our enemy and add a Rigidbody component to it, but because we have several copies of the same object, we need to take them one by one and add the same component to all of them. Maybe later, we will need to change the mass of each enemy, so again, we need to go over each one of the enemies and make the change, and here we can start to see a pattern.
One solution could be to select all the enemies using the Ctrl key (option on a Mac) and modify all of them at once, but that solution won't be of any use if we have enemy copies in other scenes. So, here is where Prefabs come in.
In this section, we will cover the following concepts related to Prefabs:
- Creating Prefabs
- Prefab-instance relationship
- Prefab variants
Creating Prefabs
A Prefab is a Unity tool that allows us to convert custom-made objects, such as our enemy, into an Asset that defines how they can be created. We can use them to create new copies of a custom object easily, without needing to create its components and sub-objects all over again.
In order to create a Prefab, we can simply drag our custom object from the Hierarchy window to the Project window, and after doing that you will see a new Asset in your project files. The Project window is where you can navigate and explore all your project files; so, in this case, our Prefab is the first Asset we ever created. Now, you can simply drag the Prefab from the Project window into the Scene to easily create new Prefab copies, as illustrated in the following screenshot:

Figure 3.27 – Creating a Prefab
Now, we have a little problem here. If you pay attention to the Hierarchy window, you will see the original Prefab objects and all the new copies with its names in blue, while the enemies created before the Prefab will have its names in black. The blue in a name means that the object is an instance of a Prefab, meaning that the object was created based on a Prefab. We can select those blue named objects and click the Select button in the Inspector to select the original Prefab that created that object. This is illustrated in the following screenshot:

Figure 3.28 – Detecting Prefabs in the hierarchy
So, the problem here is that the previous copies of the Prefab are not instances of the original Prefab, and sadly there's no way to make them be connected to the Prefab. So, in order to make that happen, we need to simply destroy the old copies and replace them with copies created with the Prefab. At first, not having all copies as instances doesn't seem to be a problem, but it will be in the next section of this chapter, where we will explore the relationship between the Prefabs and their instances.
Prefab-instance relationship
An instance of a Prefab has a binding to the Prefab that helps to revert and apply changes easily between them. If you take a Prefab and make some modifications to it, those changes will be automatically applied to all instances across all the scenes in the project, so we can easily create a first version of the Prefab, use it all around the project, and then experiment with changes.
To practice this, let's say we want to add a Rigidbody component to the enemies so that they can fall. In order to do so, we can simply double-click the Prefab file and we will enter Prefab Edit Mode, where we can edit the Prefab isolated from the rest of the scene. Here, we can simply take the Prefab root object and add the Rigidbody component to it. After that, we can simply click on the Scenes button in the top-left part of the Scene window to get back to the scene we were editing, and now, we can see that all the Prefab instances of the enemy have a Rigidbody component, as illustrated in the following screenshot:

Figure 3.29 – Prefab Edit Mode
Now, what happens if we change a Prefab instance instead? Let's say we want one specific enemy to fly, so they won't suffer the effect of gravity. We can do that by simply selecting the specific Prefab and unchecking the Use Gravity checkbox in the Rigidbody component. After doing that, if we play the game, we will see that only that specific instance will float. That's because changes of an instance of a Prefab became an override, and we can see that clearly if you see how the Use Gravity property of that instance becomes bold in the Inspector. Let's take another object and change its Scale property to make it bigger. Again, we will see how the Scale property becomes bold, and with a little bar at its left. The Use Gravity checkbox can be seen in the following screenshot:

Figure 3.30 – Use Gravity being highlighted as an override
The overrides have precedence over the Prefab, so if we change the scale of the original Prefab, the one that has a scale override won't change, keeping its own version of the scale, as illustrated in the following screenshot:

Figure 3.31 – One Prefab instance with an scale override
We can easily locate all overrides of an instance using the Overrides dropdown in the Inspector, locating all the changes our object has. It not only allows us to see all the overrides, but also reverts any override we don't want and applies the ones we want. Let's say we regretted the lack of gravity of that specific Prefab—no problem! We can just locate the override and revert it. The process is illustrated in the following screenshot:

Figure 3.32 – Reverting a single override
Also, let's imagine that we really liked the new scale of that instance, so we want all instances to have that scale—great! We can simply hit the Apply button, select the specific change, and all instances will have that scale (except the ones with an override), as illustrated in the following screenshot:

Figure 3.33 – The Apply button
Also, we have the Revert All and Apply All buttons, but use them with caution, because you can easily revert and apply changes that you are not aware of.
So, as you can see, Prefab is a really useful Unity tool to keep track of all similar objects and apply changes to all of them, and also have specific instances with few variations. Talking about variations, there are other cases where you will want to have several instances of a Prefab with the same set of variations—as an example, flying enemies and grounded enemies—but if you think about that, we will have the same problem we had when we didn't use Prefabs, so we need to manually update those varied versions one by one.
Here, we have two options: one is to create a brand new Prefab just to have another version with that variation. This leads to the problem that if we want all types of enemies to suffer changes, we need to manually apply the changes to each possible Prefab. The second option is to create a Prefab variant. Let's review the latter.
Prefab variants
A Prefab variant is the act of creating a new Prefab but based on an existing one, so the new one inherits the features of the base Prefab. This means that our new Prefab can have differences with the base one, but the features that they have in common are still connected.
To illustrate this, let's create a variation of the enemy Prefab that can fly: the flying enemy Prefab. In order to do that, we can select an existing enemy Prefab instance in the Hierarchy window, name it Flying Enemy, and drag it again to the Project window, and this time we will see a prompt, asking which kind of Prefab we want to create. This time, we need to choose Prefab Variant, as illustrated in the following screenshot:

Figure 3.34 – Creating Prefab variants
Now, we can enter the Prefab Edit Mode of the variant by double-clicking it, and then add a cube as the jet pack of our enemy, and also uncheck the Use Gravity property for the enemy. If we get back to the Scene, we will see the variant instance being changed, and the base enemies aren't changed. You can see this in the following screenshot:

Figure 3.35 – Prefab variant instance
Now, imagine you want to add a hat to all our types of enemies. We can simply enter the Prefab Edit Mode of the base enemy Prefab by double-clicking it, and add a cube as a hat. Now, we will see that change applied to all the enemies, because remember: the Flying Enemy Prefab is a variant of the base enemy Prefab, meaning that it will inherit all the changes of that one.
We have created lots of content so far, but if our PC turns off for some reason, we will certainly lose it all, so let's see how we can save our progress.