ScriptableObject
This is basically a set of data as a unity asset. It can be created just like any other unity asset. The advantage is that you're not storing unnecessary data or duplicate data.
Create it like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName="New Item", menuName="Item")]
public class Item : ScriptableObject
{
public string itemName;
public int itemLevel;
public Texture2D itemIcon;
}
And use it like this
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemHolder : MonoBehaviour
{
public Item itemToHold;
// Start is called before the first frame update
void Start()
{
Debug.Log("I am holding {itemToHold.name}");
}
}
Saving
SO's can't be saved during runtime outside of the editor!
Recommended Mode: To serialize data you should use SerializedObject and SerializedProperty. This functionalities make sure you have a prober undo-state and flush all changes out. Example for Arrays:
[CreateAssetMenu(fileName = "SerializedArrayTester", menuName = "DEBUG")]
public class SerializedArrayTester : ScriptableObject
{
[SerializeField]
public float[] speed = {0f, 1f, 2f, 3f};
}
[CustomEditor(typeof(SerializedArrayTester))]
public class SerializedArrayTesterEditor : Editor
{
SerializedProperty m_Speed;
public override void OnInspectorGUI()
{
serializedObject.Update();
m_Speed = serializedObject.FindProperty("speed");
for (int x = 0; x < m_Speed.arraySize; x++)
{
// get array element at x
SerializedProperty property = m_Speed.GetArrayElementAtIndex(x);
// Edit this element's value.
// in this case limit the float's value to a positive value.
property.floatValue = Mathf.Max (0,property.floatValue);
}
// draw property with it's children
EditorGUILayout.PropertyField(m_Speed,true);
serializedObject.ApplyModifiedProperties();
}
}
Dirty Mode: Add an Undo.RecordObject action before changing any values. This will mark everything dirty and add an undo state:
EditorGUI.BeginChangeCheck();
float areaOfEffect = SomeAction();
if (EditorGUI.EndChangeCheck())
{
// Like this:
Undo.RecordObject(target, "Changed Area Of Effect");
t.areaOfEffect = areaOfEffect;
}
Very dirty Mode: In editor mode you need to set it dirty and force the asset database to save all open files:
EditorUtility.SetDirty(theAsset);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();