How to get System.Object in an editor script

I make a script that can change values of ScriptableObjects. It takes a UnityEngine.Object (the ScriptableObject), a System.Object (the change) and a type that specifies which type gets changed. I have a simple editor script that says when the type is an integer it will create an EditorGUILayout.IntField(). When the type is a float it will create a FloatField… The problem is i can’t get the System.Object variable. I tried getting it with a SerializedProperty but its value was null. I tried getting it through the script but when i ran the game the value dropped to zero. Does anyone know how to fix this issue?

This is my Script.

using UnityEngine;

public enum VariableType
{
    Int,
    Float,
    Bool,
    String
}

public class VariableChange : MonoBehaviour
{
    #region - Conditions -
    //General
    public enum ConditionType
    {
        Collision
    }

    public ConditionType conditionType;

    //Collision
    public string collisionTag;
    #endregion

    #region - VariableChange -
    //General
    public VariableType varType;

    public Object variable;
    public object change;

    //Int/Float
    public enum OperatorationType
    {
        Addition,
        Subtraction,
        Multiplication,
        Division,
        Equals
    }
    public OperatorationType operationType;

    //Bool
    public bool invertValue;

    //String
    //For Later
    #endregion

    void ChangeVariable()
    {
        switch (varType)
        {
            case VariableType.Int:
                {
                    IntVar tempVar = (IntVar)variable;
                    switch (operationType)
                    {
                        case OperatorationType.Addition:
                            tempVar.value += (int)change;
                            break;
                        case OperatorationType.Subtraction:
                            tempVar.value -= (int)change;
                            break;
                        case OperatorationType.Multiplication:
                            tempVar.value *= (int)change;
                            break;
                        case OperatorationType.Division:
                            tempVar.value /= (int)change;
                            break;
                        case OperatorationType.Equals:
                            tempVar.value = (int)change;
                            break;
                    }
                }
                break;
            case VariableType.Float:
                {
                    FloatVar tempVar = (FloatVar)variable;
                    switch (operationType)
                    {
                        case OperatorationType.Addition:
                            tempVar.value += (float)change;
                            break;
                        case OperatorationType.Subtraction:
                            tempVar.value -= (float)change;
                            break;
                        case OperatorationType.Multiplication:
                            tempVar.value *= (float)change;
                            break;
                        case OperatorationType.Division:
                            tempVar.value /= (float)change;
                            break;
                        case OperatorationType.Equals:
                            tempVar.value = (float)change;
                            break;
                    }
                }
                break;
            case VariableType.Bool:
                {
                    BoolVar tempVar = (BoolVar)variable;
                    if (!invertValue)
                        tempVar.value = (bool)change;
                    if (invertValue)
                        tempVar.value = !tempVar.value;
                }
                break;
            case VariableType.String:
                {
                    //StringVar tempVar = (StringVar)variable;
                    //tempVar.value += (int)change;
                }
                break;
        }
    }

    void OnTriggerEnter(Collider collision)
    {
        if (conditionType != ConditionType.Collision)
            return;

        if (collision.tag == collisionTag)
        {
            ChangeVariable();
        }
    }
}

This is the custom editor of it.

#if UNITY_EDITOR
using UnityEditor;

[CustomEditor(typeof(VariableChange))]
public class VariableChangeEditor : Editor
{
    // - Conditions -
    SerializedProperty conditionType;

    //Collision
    SerializedProperty collisionTag;

    // - VariableChange -
    SerializedProperty variable;
    SerializedProperty varType;

    //Int, Float
    SerializedProperty operationType;

    //Bool
    SerializedProperty invertValue;

    //String
    //For Later

    //Script
    VariableChange script;

    void OnEnable()
    {
        script = (VariableChange)target;
       
        #region Conditions
        //General
        conditionType = serializedObject.FindProperty(nameof(conditionType));

        //Collision
        collisionTag = serializedObject.FindProperty(nameof(collisionTag));
        #endregion

        #region - VariableChange -
        //General
        variable = serializedObject.FindProperty(nameof(variable));
        varType = serializedObject.FindProperty(nameof(varType));

        script.change = new object();

        //Int, Float
        operationType = serializedObject.FindProperty(nameof(operationType));

        //Bool
        invertValue = serializedObject.FindProperty(nameof(invertValue));

        //String
        //For Later
        #endregion
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();

        #region Conditions
        EditorGUILayout.PropertyField(conditionType);

        if (conditionType.enumValueIndex == (int)VariableChange.ConditionType.Collision)
        {
            EditorGUILayout.PropertyField(collisionTag);
        }
        #endregion

        EditorGUILayout.Space();

        #region - VariableChange -
        EditorGUILayout.PropertyField(variable);
        EditorGUILayout.PropertyField(varType);

        switch (varType.enumValueIndex)
        {
            case (int)VariableType.Int:
                {
                    if (script.change.GetType() != typeof(int))
                        script.change = 0;
                    script.change = EditorGUILayout.IntField("Change", (int)script.change);
                    EditorGUILayout.PropertyField(operationType);
                }
                break;
            case (int)VariableType.Float:
                {
                    if (script.change.GetType() != typeof(float))
                        script.change = 0f;
                    script.change = EditorGUILayout.FloatField("Change", (float)script.change);
                    EditorGUILayout.PropertyField(operationType);
                }
                break;
            case (int)VariableType.Bool:
                {
                    if (script.change.GetType() != typeof(bool))
                        script.change = false;
                    if (!invertValue.boolValue)
                        script.change = EditorGUILayout.Toggle("Change", (bool)script.change);
                    EditorGUILayout.PropertyField(invertValue);
                }
                break;
            case (int)VariableType.String:
                {
                    if (script.change.GetType() != typeof(string))
                        script.change = "";
                    script.change = EditorGUILayout.TextField("Change", (string)script.change);
                    //Note: Values for changing string changing procedure
                }
                break;
        }
        #endregion

        serializedObject.ApplyModifiedProperties();
    }
}
#endif

This needs more explanation, some background of what you’re trying to do (it could be already supported or there’s a much easier solution) and point us to the line or block of code where you’re having problems with, and what these problems are, what you’ve tried.

Note that an Editor script has a target(s) properties that give you the object(s) the editor script is currently working with.

I wonder why do you use UnityEngine.Object rather than ScriptableObject?

I’ll second that wonder. I have never had a call to use this master parent class.

Anytime you reach for UnityEngine.Object (or especially the basic C# object), you probably want to simply delete the code you have and start over. Using such a generic thing is almost always proof that you didn’t understand or solve the problem properly.

Thanks for your help. I changed the UnityEngine.Object to ScriptableObject makes more sense now.
My ScriptableObjects are basically just variables as ScriptableObjects. So i can edit them wherever I want.
This for example:

using UnityEngine;

[CreateAssetMenu(menuName = "Variables/FloatVariable")]
public class FloatVar : ScriptableObject, ISerializationCallbackReceiver
{
    public float initialValue;
    //Runtime value
    [System.NonSerialized]
    public float value;

    public void OnBeforeSerialize() { }

    public void OnAfterDeserialize()
    {
        value = initialValue;
    }
}

I have this script 3 times more for Int, Bool, String.
I wanted to make a script that has a condition and when this condition is fulfilled I change the ScriptableObject value.
I used a System.Object for the change of the variable because it can store an int value, a float value etc. I mean with that approach i can easily say i want to change this variable of type int with the value 5 or change this string by adding a “Hello”. But using the editor target Property doesn’t work because the value resets after running the game and SerializedProperty not working with System.Object. Is there maybe some other solution to that?

I’m sorry… what? This has to be the most absurd thing I’ve seen you say. Have you never made a system that’s agnostic to the type of objects its using?

Why not make a generic base class scriptable object? Unity supports serialising generics so long as they have a concrete type. You also don’t need to use the serialisation callback reciever, and this is NOT an appropriate use of it either, and can just use regular Unity callbacks instead:

public abstract class ValueObjectBase<T> : ScriptableObject
{
    [SerializeField]
    private T initialValue;  
  
    private T value = default;
  
    public T Value { get => value; set => this.value = value; }

    private void OnEnable()
    {
        value = initialValue;
    }
    private void OnValidate()
    {
        value = initialValue;      
    }
}

//usage
[CreateAssetMenu(menuName = "Objects/Int Object")]
public class IntObject :  ValueObjectBase<int> { }

Oh im such an idiot thanks for the help. Entirely forgot that I can do that.