If you’ve ever wanted to save some data in Unity that multiple gameobjects need to reference then you should lookup ScriptableObject this is very similar to a GameObject except it does not live in the scene. Instead you create them in your project window and you can then drag them and reference them in GameObjects etc. When selected in the project window you get the usual inspector allowing you to edit them.
In this post I have a small script to simplify this and an example Palette object in just a few lines of code.
There’s a bit of work involved in creating a scriptable object so I use a base class to do that for me. This just defines the function to be called by a create menu item and the function creates a new scriptable object at the currently selected project location:
using UnityEngine; using System.Collections; #if UNITY_EDITOR using UnityEditor; using System.IO; #endif public class PhiObject<T> : ScriptableObject where T : PhiObject<T> { #if UNITY_EDITOR public static void Create(string name) { string path = AssetDatabase.GetAssetPath(Selection.activeObject); if(path.Length == 0){ // no asset selected, place in asset root path = "Assets/"; } else if(Directory.Exists(path)){ // place in currently selected directory path += "/"; } else{ // place in current selection's containing directory path = Path.GetDirectoryName(path) + "/"; } if (path.Length > 0) { T o = (T)ScriptableObject.CreateInstance(typeof(T)); o.name = name; AssetDatabase.CreateAsset(o, path + o.name+".asset"); AssetDatabase.SaveAssets(); } } #endif }
Here’s an example of using this class, it shows you how easily you can now create an object to hold whatever data you want. The example is a palette, a simple array of colors:
using UnityEngine; using System.Collections; #if UNITY_EDITOR using UnityEditor; #endif public class PhiPalette : PhiObject<PhiPalette> { // Add the parameters you want to store here public Color32[] colors; // And then replace Palette with a name of what this is #if UNITY_EDITOR [MenuItem("Assets/Create/Phi/Palette")] public static void CreatePalette() { Create("New Palette"); } #endif }
That’s it you can now create a palette object by right clicking in the project window and selecting Create/Phi/Palette, then when you select it you can edit it in the inspector.
Now you have your object you can reference it in other GameObjects like so:
using UnityEngine; using System.Collections; public class CycleColors : MonoBehaviour { public PhiPalette palette; Material mat; void Awake () { MeshRenderer renderer = GetComponent<MeshRenderer>(); if(renderer != null) { mat = renderer.material; } } void Update () { // Use our palette - just cycle through it one color every second mat.color = palette.colors[(int)(Time.time % palette.colors.Length)]; } }
And you can drag your created palette to the palette field on your object: