Editor script: refer to selected ScriptableObject

66 Views Asked by At

Another way to phrase this question would be "Get ScriptableObject from selection in editor code".

I have a public class DialogueObject : ScriptableObject from which I create many SOs. I'd like to automate some actions around these SOs like populating data using editor script but I can't figure out or Google-Fu how to get a handle on them.

This does not work (NullReferenceException):

DialogueObject obj = Selection.activeGameObject.GetComponent<DialogueObject>();

So, how to select a ScriptableObject in the project window and edit it's data via editor scripting?

Update: I discovered that taking it as a public variable and assigning it in the inspector works (obj = (DialogueObject)EditorGUILayout.ObjectField("DialogueObject", obj, typeof(DialogueObject));), but I'd prefer to lift it from the Selection object instead, so still looking for help.

2

There are 2 best solutions below

1
Neighborhood Ghost On BEST ANSWER

In this case you need a custom EditorWindow. And in this editor window we can use one of the Unity Editor Events which is OnSelectionChange(), by events I mean all the message methods which are called by the Unity itself ie. Awake, OnEnable, Start, Update, etc...

OnSelectionChange() will be called when ever you select an object, regardless of Scene Hierarchy or Project View. Now you just have to get a selected object using Selection.activeObject;. After getting the current selected object you can compare and cast it to your SO type. and can draw a custom editor based on your needs.

Below is an example of a such simple:

public class SoEditor : EditorWindow
{
    [MenuItem("Tools/SoScript")] //To show an editor window...
    public static void ShowEditorWindow()
    {
        GetWindow<SoEditor>();
    }

    //This is one of the Unity message which is being called when ever the selection gets changed.
    public void OnSelectionChange()
    {
        var obj = Selection.activeObject; //Get the object/

        if (obj == null) //Check for the null.
            return;

        if (obj.GetType() == typeof(SoScript))
        {
            SoScript sos = obj as SoScript; //Here is your type casted object.

            ///Draw or populate your editor fields here...
        }
    }
}

Note: Make sure that you are using Selection.activeObject and not Selection.activeGameObject Otherwise you will get a Null Exception if the selected object is not a GameObject.

Hope this gets you to your solution...✌️

Referances: EditorWindow EditorWindow.OnSelectionChange()

1
derHugo On

Selection.activeGameObject indeed refers to a GameObject! A ScriptableObject is also not a component but rather its own asset base type.

You should simply use Selection.activeObject combined with a type check like e.g.

if(Selection.activeObject is DialogueObject obj)
{ 
    ... 
}

There is actually also no need for an EditorWindow in specific.

You can rather simply directly subscribe to Selection.selectionChanged.