Drag and drop Scriptable Object to scene

How to automaticaly create GameObject with Component that referencing to ScriptableObject we drag in droped?

Editor internally has ability to drag and drop Mesh to scene although it inherit from Object, not Mono Behavoiur.

2 Likes

Did you find a solution to this? Would be very handy.

1 Like

no :frowning:

Here is a good reference on how you can do it: Editor drag&drop override - Questions & Answers - Unity Discussions .

1 Like

Why though, what s the point? A mesh, you use as an example has a well predefined way to get used in a scene from predifined components(MeshFilter/ MeshRenderer), thus an automated process makes sense to exist. A ScriptableObject on the other hand is too generic, you obviously realize that, so you ask for a generic Monobehaviour with a single field and nothing more. Which bits me what purpose serve, if you want to use said scriptable you ll need to reference given MonoBehaviour and then the scriptable.

So the whole fuctionality makes sence if it is defined for specific subtype of a scriptable, where you ll have to create a Componenet to handle the specific type (a well defined process, like the one used for a Mesh).

Anyway, you ll need either to manually create a MonoBehaviour for all scriptable subtypes, or use CodeDom to automate the creation, or create one(monobehaviour) with the parent type(field) and then cast it for specific use(the scriptable in the field).

1 Like

There is some cases when SO designed for one MB only. So has a reason to create MB when SO dragged to scene. For example - Post Processing Profile is an SO, and may be reasonable to create camera with image effect component that refer on Profile SO, is not it?

Scriptable Object is the asset counterpart of the MonoBehaviour. If you need an object in the scene (hierarchy), you create MonoBehaviour (you need the position and/or visual part), if you don’t need position in the world and you don’t need visual representation, you use Scriptable Object.
It is simple as that.

MonoBehaviour - things in the game world
ScriptableObject - things among the assets

It would be very helpful to figure out a solution for this. I haven’t been able to, as of yet.
My goal is to allow scriptable assets to have a IDroppableSO interface, which has a function OnDropIntoScene(Vector3 position). Some sort of manager detects the drag and dropping of the SO, detects it has that interface, and runs the function.

This would allow me to allow SO’s to have custom features when dragged and dropped into the scene! For example, I have CharacterData which would create a character spawner, and ItemData that would create a item spawner.

1 Like

I am found a solution.
There is undocumented callback Editor.OnSceneDrag(SceneView sceneView) exacly for this purpose.
In my example DynamicHairData are Scriptable Object , DynamicHair are Monobehaviour that use DynamicHairData .
If DynamicHairData was dragged on existing GameObject with DynamicHair component then it assign at its field. If DynamicHairData was dragged on empty space a new GameObject with DynamicHair component are created, then DynamicHairData assign at Field.

floor.RaycastDoublesided(r, ref pos) performs intersection of mouse ray with world`s XZ plane to place new object on it.

Also you can find SOs drag-and-drop example in [Materials editor script](UnityCsReference/Modules/AssetPipelineEditor/ImportSettings/ModelImporterMaterialEditor.cs at 9c7b88327d1b48000ea94dc52a405068a140980f · Unity-Technologies/UnityCsReference · GitHub).

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using Polyflow;
using PolyflowEditor;

[CustomEditor(typeof(DynamicHairData))]
public class DynamicHairDataInspector : Editor {

    internal void OnSceneDrag(SceneView sceneView) {
       
        Event e = Event.current;
        GameObject go = HandleUtility.PickGameObject(e.mousePosition, false);

        if (e.type == EventType.DragUpdated) {
            if (go) {
                DragAndDrop.visualMode = DragAndDropVisualMode.Link;
            } else {
                DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
            }
            e.Use();
        } else if (e.type == EventType.DragPerform) {
            Debug.Log("Drag performed");
            DragAndDrop.AcceptDrag();
            e.Use();
          
            DynamicHair dhcomponent = go? go.GetComponent<DynamicHair>() : null;
            if (!dhcomponent) {
                go = new GameObject(target.name);
                Plane floor = new Plane(Vector3.up, Vector3.zero);
                Ray r = HandleUtility.GUIPointToWorldRay(e.mousePosition);
                Vector3 pos = r.GetPoint(1);
                floor.RaycastDoublesided(r, ref pos);
                go.transform.position = pos;
                Selection.activeGameObject = go;
            }
            go.AddComponent<DynamicHair>().Data = target as DynamicHairData;
        } 
    }
 


}
8 Likes

Fantastic! Thank you so much friend!!! Looks like the correct like for the materials is here, for anyone interested

3 Likes

at the moment (2021.2.11f1) the correct signature is this: void OnSceneDrag(SceneView sceneView, int index)