I recently had the need to create a prefab at runtime. This is really useful for creating your own level editors or if you want to use programming logic to build an object that can then be saved and reused later.
Note: This is an advanced tutorial, recommended for those already familiar with the Unity3D game engine.
As an example, I created an empty object (a hot pink cube) that can be instantiated using:
Why would I do this? Well, it’s part of a more generic ability to instantiate any prefab by name. But, if the name is not found, the hot-pink cube serves as a visual representation of the “object not found” without actually breaking out of the code at runtime.
The code is pretty straightforward. It assumes you have a static Object placeholder for storing a reference to the prefab. Then, simply:
- Use PrefabUtility.CreateEmptyPrefab() to create a placeholder for the prefab.
- Use GameObject.CreatePrimative() to create a cube (PrimitiveType.Cube).
- Modify the object, in this case adding a Rigidbody with AddComponent() and changing the color
- Use PrefabUtility.ReplacePrefab() to update the prefab with the new object.
using UnityEngine; using System.Collections.Generic; #if UNITY_EDITOR using UnityEditor; #endif //... public static Object emptyObj; //... #if UNITY_EDITOR string fileName = "empty_object_01"; string fileLocation = "Assets/Resources/Prefabs/"+fileName+".prefab"; emptyObj = PrefabUtility.CreateEmptyPrefab(fileLocation); GameObject tempObj = GameObject.CreatePrimitive(PrimitiveType.Cube); tempObj.name = fileName; tempObj.AddComponent<Rigidbody>(); tempObj.renderer.material.color = new Color(1.0f, 0.0f, 0.5f); PrefabUtility.ReplacePrefab(tempObj, emptyObj, ReplacePrefabOptions.ConnectToPrefab); #endif
Note the use of the precompiler directive: #if UNITY_EDITOR. This is used because the PrefabUtility (part of the UnityEditor namespace) is not available outside the Unity Editor. That means the must be run at least once from within the editor (in order to generate the object). Afterwards, the object is already generated and can be pulled from the resources folder automatically (see the full example on accessing Global Prefabs by Name)
It is also possible to do this with one less step using PrefabUtility.CreatePrefab(), but I wanted to demonstrate use of the ReplacePrefab() function. If you can get this to work, you’ll have no problem getting the simpler version to work as well.
A full working version of the code is available on GitHub as part of my Global Prefab example.