Drag & Drop ScriptableObject into scene

TLDL: How can I allow drag&drop of a custom ScriptableObject into the scene? (and spawn a GameObject with some component referencing it)

I’m creating a volume rendering plugin, where I want to allow users to import medical datasets in the editor (“.raw”, “.dcm”, etc.), and then drag&drop into the scene, similar to how you can import meshes.

The datasets are implemented as a ScriptableObject that I’m creating a ScriptedImporter for. Basically I want to let users drag & drop these into a scene, which should spawn a GameObject and add a custom component to it that references this ScriptableObject.

Is this possible? I could of course add a “spawn” button to my ScriptedImporterEditor, but it would be nicer if I could allow users to drag&drop into the scene. This seems to be how meshes work (Mesh is an Object, and when you drag&drop a GameObject containing a MeshFilter referencing this Mesh will be spawned).

1 Like

Never played with this sort of thing, but there seems to be a class in the Unity editor for this: Unity - Scripting API: DragAndDrop

Looks like you should be able to use AddDropHandler to register a scene drop handler, so perhaps you can use this to pick up when you drag your specific scriptable object and use that to instantiate your game object.

1 Like

That’ exactly what I needed! Thanks a lot :slight_smile: (will share the full solution afterwards)

And here’s the code, for anyone interested:

using UnityEditor;
using UnityEngine;

namespace UnityVolumeRendering
{
    static class DragDropHandler
    {
        [InitializeOnLoadMethod]
        static void OnLoad()
        {
            DragAndDrop.AddDropHandler(OnSceneDrop);
            DragAndDrop.AddDropHandler(OnHierarchyDrop);
        }

        private static DragAndDropVisualMode OnSceneDrop(Object dropUpon, Vector3 worldPosition, Vector2 viewportPosition, Transform parentForDraggedObjects, bool perform)
        {
            if (perform)
            {
                VolumeDataset datasetAsset = (VolumeDataset)DragAndDrop.objectReferences[0];
                VolumeObjectFactory.CreateObject(datasetAsset);
            }
            return DragAndDropVisualMode.Move;
        }

        private static DragAndDropVisualMode OnHierarchyDrop(int dropTargetInstanceID, HierarchyDropFlags dropMode, Transform parentForDraggedObjects, bool perform)
        {
            if (perform)
            {
                VolumeDataset datasetAsset = (VolumeDataset)DragAndDrop.objectReferences[0];
                VolumeRenderedObject spawnedObject = VolumeObjectFactory.CreateObject(datasetAsset);
                GameObject parentObject = (GameObject)EditorUtility.InstanceIDToObject(dropTargetInstanceID);
                if (parentObject)
                {
                    spawnedObject.gameObject.transform.SetParent(parentObject.transform);
                }
            }

            return DragAndDropVisualMode.Move;
        }
    }
}

There’s one handler for drag&drop into the scene view, and one for the hierarchy view (which attaches it to a parent).

4 Likes