I use Scriptable Objects to create Items for my Unity Game. Let's say I create a Stick, a Sword and a Helmet. Now to use them, I need to drag them into a list and on game start, each item get's an ID assigned which is also the position in the list, as I simply loop through the list to assign ID's. Now I can access the item by using the index it has or, as shown in most of the tutorials about ScriptableObjects, we can then add the item and the id to a Dictionary to better access them.
Stick is 0, Sword is 1 and Helmet is 2. Now I decide to remove the sword with a patch so helmet gets the ID of 1. Now every savegame is broken as swords become helmets.
How can I handle assigning fixed ID's which wont change and wont be taken by another item until I really want to assign it again? I could of course hard-code the id for every ScriptableObject I create but as you can imagine, managing hard-coded IDs seems not like a good idea.
In order to create a Scriptable Object, you'll need to first add to the Create menu you've used to create materials and scripts. To do this, you'll use the attribute CreateAssetMenu and specify the default filename and location within the menu. Also, you'll need to change what class CharStats is inheriting from.
ScriptableObjects aren't persistent. Only in the Editor. When you make a build, run your game, change something in the ScriptableObject, exit the game and restart it, it won't retain the change. You still need a proper save system to achieve persistence.
You cannot save scriptable objects during runtime. Use an editor script instead. Otherwise, if you are loading a "spreadsheet" in runtime as part of the application/game, use JSONUtility instead to serialize and deserialize common [Serializable] classes and structs with [SerializeField] instead.
Here is my take on it :
BaseScriptableObject.cs :
using System;
using UnityEditor;
using UnityEngine;
public class ScriptableObjectIdAttribute : PropertyAttribute { }
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(ScriptableObjectIdAttribute))]
public class ScriptableObjectIdDrawer : PropertyDrawer {
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
GUI.enabled = false;
if (string.IsNullOrEmpty(property.stringValue)) {
property.stringValue = Guid.NewGuid().ToString();
}
EditorGUI.PropertyField(position, property, label, true);
GUI.enabled = true;
}
}
#endif
public class BaseScriptableObject : ScriptableObject {
[ScriptableObjectId]
public string Id;
}
Weapon.cs :
using System;
using UnityEngine;
[CreateAssetMenu(fileName = "weapon", menuName = "Items/Weapon")]
public class Weapon : BaseScriptableObject {
public int Attack;
public int Defence;
}
Result :
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With