Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
9
Question by Boco · Apr 12, 2011 at 09:45 PM · updategrideditorwindowdrawing

Drawing to the scene from an EditorWindow

I'm getting my feed wet with extending the Unity tools. Long story short I want to make a custom grid that I can use to snap specific objects. Right now I'm trying to make a window that shows you the grid that you can define. My issue here is that this the line drawing doesn't seem to update in a window very well.

If I toggle it on or off... doesn't update. If it's on and I select a viewport, it draw, but If I change a number, it does not update. If I change a number and select a viewport, it now draws the previous iteration as well as the last one.

I'm not even sure if I'm using the correct draw functions here. drawing gizmos didn't seem to work. As well, I got a memory leak error from this. So, any suggestions as to a better method or a way to force a draw update in the viewports.

Here is the code I have so far.

class TileWindow extends EditorWindow { var showGrid:boolean=false; var xTiles:int=24; var zTiles:int=24; var tileSize:float=1; var xOffset:float=0; var zOffset:float=0; var topLeft:Vector3; var topRight:Vector3; var botLeft:Vector3; var botRight:Vector3;

 @MenuItem ("Window/Tile View")
 static function ShowWindow () {
     EditorWindow.GetWindow (TileWindow);
 }

 function OnGUI () {
     showGrid=EditorGUILayout.Toggle("Grid View",showGrid);
     tileSize=EditorGUILayout.FloatField("Tile Size",tileSize);
     xTiles=EditorGUILayout.FloatField("X Tiles",xTiles);
     zTiles=EditorGUILayout.FloatField("Z Tiles",zTiles);
 }

 function OnInspectorUpdate () {
     xOffset=-(xTiles*tileSize)/2;
     zOffset=-(zTiles*tileSize)/2;

     if (showGrid){
         for (i=0;i<xTiles;i++){
             for (j=0;j<zTiles;j++){
                 topLeft= Vector3(xOffset+(tileSize*i),0,zOffset+(tileSize*j));
                 topRight=Vector3(xOffset+(tileSize*i+tileSize),0,zOffset+(tileSize*j));
                 botLeft= Vector3(xOffset+(tileSize*i),0,zOffset+(tileSize*j+tileSize));
                 botRight=Vector3(xOffset+(tileSize*i+tileSize),0,zOffset+(tileSize*j+tileSize));
                 Debug.DrawLine(topLeft,topRight,Color.red);
                 Debug.DrawLine(botLeft,botRight,Color.red);
                 Debug.DrawLine(topLeft,botLeft,Color.red);
                 Debug.DrawLine(topRight,botRight,Color.red);

             }
         }
     }
 }

}

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

5 Replies

· Add your reply
  • Sort: 
avatar image
26
Best Answer

Answer by rhys_vdw · Sep 07, 2012 at 01:51 AM

Oliver's answer is not entirely correct but is the correct approach. This is how I solved this problem:

 // Window has been selected
 void OnFocus() {
     // Remove delegate listener if it has previously
     // been assigned.
     SceneView.onSceneGUIDelegate -= this.OnSceneGUI;

     // Add (or re-add) the delegate.
     SceneView.onSceneGUIDelegate += this.OnSceneGUI;
 }
 
 void OnDestroy() {
     // When the window is destroyed, remove the delegate
     // so that it will no longer do any drawing.
     SceneView.onSceneGUIDelegate -= this.OnSceneGUI;
 }
 
 void OnSceneGUI(SceneView sceneView) {

     // Do your drawing here using Handles.

     Handles.BeginGUI();
     // Do your drawing here using GUI.
     Handles.EndGUI();    
 }

Once you have registered your OnSceneGUI method as a delegate listener to the onSceneGuiDelegate event in SceneView, it will be called whenever the editor draws the scene (so once for each window).

This will continue after the window is destroyed, so it must be release in OnDestroy.

The strange part is how the delegate is released and then register in OnFocus. Unfortunately EditorWindow has no Awake/Start type event. OnFocus is as a next-best. OnFocus can be called multiple times during a Window's lifetime, and the delegate should not be registered more than once. There is no way to check whether the delegate has already been registered, but removing it first will solve this.

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Soviut · Jan 12, 2013 at 09:28 PM 3
Share

You should use OnEnable() to register your delegates. And delegates can be checked http://stackoverflow.com/questions/136975/has-an-event-handler-already-been-added

avatar image rhys_vdw · Jul 24, 2013 at 01:17 PM 0
Share

Thanks for the tip on checking delegates.

I didn't check OnEnable, but it's not documented as a message received by EditorWindow. Does it work anyway?

avatar image AlkisFortuneFish rhys_vdw · Apr 12, 2017 at 08:24 AM 0
Share

I know that this is necroing a thread, but EditorWindow is a ScriptableObject, so yes.

avatar image ocimum · Dec 07, 2015 at 10:36 AM 0
Share

Thats a cool snippet, didn't know I can work with the SceneView inside EditorWindow too.

avatar image drihpee · Apr 29, 2016 at 09:08 AM 0
Share

If you got TargetParameterCountException error, then try to use static on

 void OnSceneGUI(SceneView sceneView){}

to be

 static void OnSceneGUI(SceneView sceneView) {}

don't know if this is will help or not, just figuring out when I got that exception while using the same method as describe above for drawing GUI elements on SceneView while not on Play $$anonymous$$ode.

avatar image
5

Answer by founderio · Aug 31, 2011 at 11:11 AM

I used the Delegate function of SceneView to manage this. C# Code (should work in JavaScript...):

     //Inside OnGUI or Update, does not make any difference.
     if(SceneView.onSceneGUIDelegate != this.OnSceneGUI)
     {
         SceneView.onSceneGUIDelegate += this.OnSceneGUI;
     }

When you insert this you can have a simple OnSceneGUI() function in you EditorWindow Class. BUT: The OnSceneGUI function has to have one parameter of the type SceneView. Like so:

 public void OnSceneGUI (SceneView scnView)
 {
     Handles.Button (new Vector3 (500.0f, 0, 500.0f), Quaternion.LookRotation (Vector3.up), 500.0f, 0.0f, Handles.RectangleCap);
 }

The SceneView passed each call is the SceneView that is currently drawing, so you can draw different GUIs for each SceneView. As you See, vou can even use the Handles functions. If you intend to use regular GUI functions you first have to start a GUI Block with the corresponding Handle funtions BeginGUI and EndGUI.

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image rhys_vdw · Sep 06, 2012 at 01:15 AM 1
Share

I tried to upvote this answer but for some reason Unity Answers doesn't permit me to do anything. I'm actually surprised I'm allowed to comment.

Anyway, great answer, you've helped me solve my problem. I'd just like to make a small correction, however.

The != operator does not do what your code implies. A better way to do this would be to declare a flag to keep track of whether you have registered your delegate yet. When I used your method Unity crashed - I attribute the reason to an infinitely extending list of delegate listeners in SceneView (one per call to OnSceneGUI).

avatar image founderio · Sep 06, 2012 at 07:07 AM 0
Share

Well, that would then be just a matter of adding the delegate correctly. As I just now found out you can just remove it before adding it, if it was not already assigned it will just be ignored.

See here: http://stackoverflow.com/questions/4093442/how-do-i-find-out-if-a-particular-delegate-has-already-been-assigned-to-an-event

avatar image rhys_vdw · Sep 06, 2012 at 04:35 PM 0
Share

I've now adopted using OnFocus and OnLostFocus to add and remove the listener, however this is not necessarily the appropriate solution for all situations.

avatar image founderio · Sep 06, 2012 at 06:13 PM 0
Share

That might work, too. It would at least save you the check in every GUI/Update call. However that will then only update the scene if the editor window in question is active (Do update calls make it to an inactive window? It's been a while since I last worked with Editor modification...). But still, that might be just the right thing for some cases, depending on what you want to do, if it is a permenent "addon" for the scene view or just a demonstration/visualization of what is going on in the editor.

avatar image rhys_vdw · Sep 06, 2012 at 11:42 PM 0
Share

Yeah, the OnSceneGUI is fired when the window is inactive and even after it is destroyed. I'm going to add a new answer with my solution I've come to (using both your and my approach). Thanks for the tip.

avatar image
5

Answer by Acegikmo · Apr 13, 2016 at 08:05 AM

Here's a more compact version using OnEnable/OnDisable instead, which is more reliable

     void OnEnable() {
         SceneView.onSceneGUIDelegate += this.OnSceneGUI;
     }
  
     void OnDisable() {
         SceneView.onSceneGUIDelegate -= this.OnSceneGUI;
     }
  
     void OnSceneGUI(SceneView sceneView) {
         Handles.BeginGUI();
         // GUI Code here
         Handles.EndGUI();    
     }

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image brainwipe · Mar 08 at 10:02 PM 0
Share

Delighted to find a Freya Holmér answer that nails it. Massive fan.

avatar image
4

Answer by unity_B38470367AA16AF92C4C · Sep 24, 2021 at 01:27 PM

SceneView.onSceneGUIDelegate is depricated now. you should use `SceneView.duringSceneGui` instead.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
2

Answer by Bunny83 · Apr 12, 2011 at 11:51 PM

Well, the editor works a bit different than the game runtime. The GUI and the sceneview is only drawn if it's needed. Every EditorWindow have a Repaint function. The SceneView is also derived from EditorWindow. The SceneView class is not documented yet, but if you use visual studio (c#) you can view all members.

Just in case that you can't find it:

SceneView.lastActiveSceneView.Repaint();
Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Socapex · Dec 27, 2016 at 08:15 PM 0
Share

HandleUtility.Repaint() also works great.

avatar image kalahario · Jan 24, 2019 at 03:19 PM 0
Share

@Bunny83 I've been trying to solve this related question (https://forum.unity.com/threads/prefab-mode-changes-only-one-of-several-prefab-copies-until-the-others-are-manually-selected.613735/) for quite a while. I'll really appreciate your help.

avatar image kalahario kalahario · Jan 24, 2019 at 03:29 PM 0
Share

@Bunny83 I a private conversation with one of the Unity reps on the forum, after going through my bug report, he said it's not a bug.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

12 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

DrawWireDisc in scene from custom EditorWindow 0 Answers

EditorWindow.Update without Unity having focus 1 Answer

How to automatically rearrange a path on a grid ? 0 Answers

EditorApplication.update in Background 1 Answer

Invoke inspector update (from editorwindow) 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges