Newbie here
My goal:
I want to modular generate different abilties in the inspector that can be attached to a Monobehaviour. Abilty values can also be tweaked in the inspector seperatly from each other
What i came up with so far
Every unique Ability is a ScriptableObject asset. It contains an array of AbilityProperties. AbilityProperty is also an ScriptableObject and acts as a “superclass”. Unique AbilityProperties derive from AbilityProperty and implement a simple interface, which only holds a method called execute(). With a custom drawer you are able to attach unique AbilityProperties and tweak the values of every single one of them.
The problem
Now the big obvious flaw in this design is, when i tweak an AbilityProperty value in one Ability it will change in every other Ability too. Because there is only one AbilityProperty_Damage ScriptableObject. Or I have too create a ScriptableObject Asset for every property of every ability which seems nuts.
So anyone has an idea how to tackle this problem? Since I’m at the beginning I can redesign the whole thing.
The code
Sorry for the wierd formating but here i had an issue with the web editor:
[CreateAssetMenu(fileName = "Ability")] public class Ability : ScriptableObject { public Property[] properties; }
public interface IProperty { void execute(); }
public class AbilityProperty : ScriptableObject { public string propName; }
[CreateAssetMenu(fileName = "propDamage")] public class Property_Damage : Property, IProperty { public int damageAmont;public void execute() { // some damage specific logic }
}
using UnityEngine; using UnityEditor; using System.Reflection; [CustomPropertyDrawer(typeof(AbilityProperty))] public class AbilityPropertyDrawer : PropertyDrawer { public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { if (property.objectReferenceValue == null) return base.GetPropertyHeight(property, label);var modifier = property.objectReferenceValue as AbilityProperty; var fields = modifier.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance); return base.GetPropertyHeight(property, label) * (float)(fields.Length + 1); } public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { position.height = base.GetPropertyHeight(property, label); EditorGUI.PropertyField(position, property); if (property.objectReferenceValue == null) return; var modifier = property.objectReferenceValue as AbilityProperty; var fields = modifier.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance); var sObj = new SerializedObject(property.objectReferenceValue); position.x += 20f; position.xMax -= 38f; foreach (var field in fields) { position.y += position.height; EditorGUI.PropertyField(position, sObj.FindProperty(field.Name)); } sObj.ApplyModifiedProperties(); }
}