Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Is there a way to draw gizmos in a scriptable object?

Discussion in 'Editor & General Support' started by PlayCreatively, Nov 21, 2020.

  1. PlayCreatively

    PlayCreatively

    Joined:
    Jan 25, 2016
    Posts:
    94
    I have multiple prefabs which are snippets of a level which I then stitch together procedurally. I also have a SO sub asset in each prefab which has additional data about the level snipped like entrance locations for example which I use to chain them together. I manually edit the positions in the inspector but since I can't draw gizmos while editing the SO I don't get any visual feedback of where the position is.
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,722
    Why use a ScriptableObject for this? I would just use empty GameObjects that are part of the Prefab's hierarchy to mark locations. In fact I'm doing exactly that in a project I'm currently working on to achieve this effect:
     
    Kurt-Dekker likes this.
  3. PlayCreatively

    PlayCreatively

    Joined:
    Jan 25, 2016
    Posts:
    94
    I can but I was hoping SO had some gizmo features to simplify this. I've got tons more data in the SO so it makes perfect sense to edit the positions there as well.
     
  4. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,722
    You'd have to write some custom Editor script(s) I think.
     
  5. joshrs926

    joshrs926

    Joined:
    Jan 31, 2021
    Posts:
    105
  6. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,881
    Fowi likes this.
  7. joshrs926

    joshrs926

    Joined:
    Jan 31, 2021
    Posts:
    105
    I was in the car parked at the grocery store at the time. I did mess around with it later and found that while I'm pretty sure you can put that attribute on a method anywhere such as in a Scriptable Object, the method must be static and have a Component type parameter which I believe is what MonoBehaviour inherits from and not Scriptable Object. That method will then be called for all instances of that component type in the scene. So unfortunately I don't think the DrawGizmo attribute is the answer for rendering stuff for Scriptable Objects in the scene view. I suppose its use would be if you wanted to move your in-editor scene view gizmos rendering code out of MonoBehaviour game code and into a separate editor only code file. That way you can keep your game code and editor code more separate.
     
    Fowi and noobler like this.
  8. tsukimi

    tsukimi

    Joined:
    Dec 10, 2014
    Posts:
    51
    Hello! I know this is an old question, but I think it's an important enough question to share my solution (after some researching on web).
    There's an editor class named Handles, that can do some basic gizmo that Gizmos can do, and it can be called in
    SceneView.duringSceneGui
    delegate. So if you create custom Editor for your ScriptableObject, you can hook to
    SceneView.duringSceneGui
    and then draw your gizmos.
    A little bit tricky, but I really need to draw gizmos in ScirptableObject (it's inside Timeline), so it deserves.

    Here's my sample code:
    Code (CSharp):
    1.     [CustomEditor(typeof(MyScriptableObject))]
    2.     public class MyScriptableObjectEditor : Editor
    3.     {
    4.         private void OnEnable()
    5.         {
    6.             SceneView.duringSceneGui += DrawGizmos;
    7.         }
    8.  
    9.         private void OnDisable()
    10.         {
    11.             SceneView.duringSceneGui -= DrawGizmos;
    12.         }
    13.  
    14.         private void DrawMyGizmos(SceneView sceneView)
    15.         {
    16.             // draw some Gizmos-like gizmo
    17.             Handles.DrawWireCube(Vector3.zero, Vector3.one * 2f);
    18.         }
    19.     }
     
    Last edited: Apr 23, 2023
    JackAidley likes this.
  9. Quique-Martinez

    Quique-Martinez

    Joined:
    Oct 1, 2013
    Posts:
    141
    Hi, I solved it with Unity actions. Barely tested.
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Events;
    3.  
    4. [ExecuteInEditMode]
    5. public class ScriptableObjectRenderer : MonoBehaviour
    6. {
    7.     UnityAction drawGizmosAction;
    8.     ScriptableObjectDrawingGizmo visualScriptableObject;
    9.  
    10.     void OnEnable()
    11.     {
    12.         if (visualScriptableObject is null)
    13.         {
    14.             visualScriptableObject = ScriptableObject.CreateInstance<ScriptableObjectDrawingGizmo>();
    15.             drawGizmosAction += visualScriptableObject.DrawGizmo();
    16.         }
    17.     }
    18.  
    19.     void OnDrawGizmos()
    20.     {
    21.         drawGizmosAction?.Invoke();
    22.     }
    23. }
    24.  
    25. public class ScriptableObjectDrawingGizmo : ScriptableObject
    26. {
    27.     public Vector3 position { get; set; }
    28.  
    29.     public UnityAction DrawGizmo()
    30.     {
    31.         return new UnityAction(() =>
    32.         {
    33.             Gizmos.color = Color.yellow;
    34.             Gizmos.DrawSphere(position, 0.05f);
    35.         });
    36.     }
    37. }
     
    tsukimi likes this.