Procedural Asset Management in Unity

We've looked previously at adding our own tools to Unity's editor; now, in this short tutorial, I'll introduce you to handling the assets by script in Unity. We'll manage paths, create prefab files, generate a texture and save it to an image. Finally we'll also create a material file that uses the generated image, and all this will be done by code.

Final Result Preview

Let's take a look at the final result we will be working towards:

Step 1: Set Up the Project

Create an empty project; we won't be using anything fancy here so we shouldn't bother to import anything at all. Once that's done, create an editor script. Unity will let us use its editor classes only if we place our script in a folder named Editor. Since that doesn't exist in our project yet, we need to create it.

Now let's create a script inside it.

Step 2: Add a MenuItem

Let's clean up our script. Aside from the basic functionality, we also want to be able to use the editor classes. We need to be using UnityEditor and our script's class should extend the Editor class instead of MonoBehaviour like normal game objects do.

using UnityEngine;
using System.Collections;
using UnityEditor;
public class Examples : Editor
{
}

In our first function we'll be working with prefabs, let's call it a PrefabRoutine.

public class Examples : Editor
{
void PrefabRoutine()
{
}
}

To easly execute this function from the editor, let's add it as a MenuItem.

If you go back to the editor now (and refresh the menu), you'll notice that there's a new menu named Examples there.

If you select the Prefab Routine nothing will happen since our function is empty.

Step 3: Create a Folder

To shape our project the way we want we need to know how to create folders so we can move stuff around. Creating a folder from the script is very straightforward, all we need to do is to let unity know where the folder should be placed. To create a folder we need to use AssetDatabase class.

If we leave a constant path as an argument, each time we select our routine a new empty prefab will replace the old one. Let's assign each prefab to separate folder to counter that. To do this we need to save the most recently created folder to a string so we can use it as a path argument later. The CreateFolder function returns a GUID, which basically is the file's (or directory's) ID. There's a function that retrieves the path if we submit this ID. It's called GUIDToAssetPath; let's use it to get our folder's path.

You can test whether the created empty prefabs are packed in folders now.

Step 5: Set the Prefab

If you create a prefab then you probably don't want to leave it empty because in that case it's pretty much useless. Let's set our prefab if there's any game object selected while our routine is executing. We'll the prefab to the selected object. To get the currently selected object we can use the Selection class which has a reference to it. To set the prefab we need to call ReplacePrefab().

If you run the routine with any game object selected now then you'll notice that the created prefab is automatically set.

That's it, we have created a custom routine for prefab creation, it's not very useful but you should be able to know how to do that now if there will be a need for such a thing in your project.

At the end I also want to mention that AssetDatabase also lets you move assets around, move them to trash or delete them by calling AssetDatabase.MoveAsset(), AssetDatabase.MoveAssetToTrash() and AssetDatabase.DeleteAsset() respectively. The rest of the functionality can be found at the AssetDatabase script reference page.

Step 6: Add Another Menu Item

Let's go to another example, this time we'll create a texture and a material programmatically. Let's call this menu item Material Routine.

Step 7: Create a Texture

Now we shouldn't let all those pixels go to waste, so let's set the texture's pixels according to some kind of thought-up formula. For that we'll need two for loops to go through every pixel. To set the each pixel's color we need to call SetPixel() which takes the position of the pixel on a texture and its color as the arguments.

To assign the color we'll use the Mathf.Sin() function. The Color class can be initialized with three floats, corresponding to the red, green and blue color components, respectively. The max allowed value is 1 and min is 0, so the Sin() function suits our needs perfectly.

Let's test whether the texture gets created when we execute our routine.

Step 9: Create a Material

We've got an image and now we can create a material that uses it as a texture. Let's create a new Material.

AssetDatabase.Refresh();
new Material(Shader.Find("Diffuse"));

The created material will use a Diffuse shader. To save this material to the file, we can call AssetDatabase.CreateAsset(). This function takes an asset as the first argument, and the path as the second one.

Conclusion

That's the end of the introduction to manage your assets using scripts. If you want to expand your knowladge on the topic you can visit the Unity Editor Classes reference page, particularly the AssetDatabase script reference is worth looking into. If you need to work at a low level, you should also read the docs on System.IO to get more information on its classes and how you can use them. Thanks for your time!