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
3
Question by Athineku · Dec 11, 2013 at 09:51 AM · editoreditorwindowdrawmesh

How to flush mesh batch in editor OR how to draw a mesh for single frame in editor?

Short version: I'm drawing mesh from EditorWindow in edit mode, scene view and the mesh is not drawn for single frame, but instead it remains in scene until certain event (like saving scene) occurs - how can I make the mesh to be rendered for single frame? (For next frame I move it, so I need to be rendered in different place so original mesh is not needed to be rendered anymore.)

See the image bellow: I want to draw the blue box only once!

Problematic scene...

Long version: I want to add following functionality: user selects a Game Object (from either current scene or prefabs) and then puts it into the scene. But when the object is put there (and only at that time), I want to run some code to transform it (especially position, but I have other reasons (currently not implemented) why drag and drop from Prefabs is not enough).

For this purpose I created a EditorWindow object which creates gui to select the object to be added (I plan in future to make a list for simple fast selection) and this window also renders the mesh as preview when user moves mouse over scene view. For this reason, I do not want to create the object before user confirms it by clicking.

This is code I use (please note that instantiating the new object and transforming it is not implemented yet):

 using UnityEngine;
 using System.Collections;
 using UnityEditor;
 
 [ExecuteInEditMode]
 public class BlockAdderWindow : EditorWindow
 {
     struct CurrentSelection
     {
         public bool isSelected;
         public Vector3 position;
     }
     
     [SerializeField]
     Material previewMaterial;
     
     [SerializeField]
     bool enabled;
     
     [SerializeField]
     GameObject parentObject = null;
     
     [SerializeField]
     GameObject templateObject = null;
     
     Mesh renderMesh;
     
     CurrentSelection currentSelection;
     
     [MenuItem("Window/Block Adder")]
     static void Init()
     {
         EditorWindow.GetWindow(typeof(BlockAdderWindow)).Show();
     }
     
     void OnEnable()
     {
         SceneView.onSceneGUIDelegate += OnSceneGUI;
     }
     
     void OnDisable()
     {
         SceneView.onSceneGUIDelegate -= OnSceneGUI;
     }
     
     void OnSceneGUI(SceneView sceneView)
     {
         if(enabled)
         {
             Camera camera = sceneView.camera;
             Vector2 mousePosition = Event.current.mousePosition;
             mousePosition.y = sceneView.camera.pixelHeight - mousePosition.y;
             CalcSelection(camera, mousePosition);
         }
         
         RenderSelection();
     }
     
     void Update()
     {
         //RenderSelection();
     }
 
     void OnGUI()
     {
         EditorGUILayout.BeginVertical();
         {
             GameObject oldTemplate = templateObject;
             
             enabled = EditorGUILayout.Toggle("Enabled", enabled);
             previewMaterial = EditorGUILayout.ObjectField("Preview material", previewMaterial, typeof(Material), true) as Material;
             parentObject = EditorGUILayout.ObjectField("Parent", parentObject, typeof(GameObject), true) as GameObject;
             templateObject = EditorGUILayout.ObjectField("Template", templateObject, typeof(GameObject), true) as GameObject;
             
             renderMesh = EditorGUILayout.ObjectField("Render mesh", renderMesh, typeof(Mesh), true) as Mesh;
             
             if( (oldTemplate != templateObject) || ((templateObject != null) && (renderMesh == null)) )
             {
                 renderMesh = null;
                 
                 if(templateObject)
                 {
                     MeshFilter meshFilter = templateObject.GetComponent<MeshFilter>();
                     
                     if(meshFilter)
                     {
                         renderMesh = meshFilter.sharedMesh;
                     }
                 }
                 
                 enabled = enabled && (renderMesh != null);
             }
         }
         EditorGUILayout.EndVertical();
     }
     
     void CalcSelection(Camera camera, Vector2 mousePosition)
     {
         //currentSelection.isSelected = false;
         
         if(camera != null)
         {
             Ray ray = camera.ScreenPointToRay(mousePosition);
             RaycastHit hit;
             
             if(Physics.Raycast(ray, out hit))
             {
                 currentSelection.isSelected = true;
                 currentSelection.position = hit.point;
                 //Debug.Log("Selected " + hit.collider.gameObject.name);
             }
         }
     }
     
     void RenderSelection()
     {
         if(enabled && currentSelection.isSelected)
         {
             Graphics.DrawMesh(renderMesh, currentSelection.position,
                 Quaternion.identity, previewMaterial, 0);
         }
     }
 }

Problem is with line Graphics.DrawMesh(...) - it does not draw the mesh for single frame only - instead, it remains there so when user moves with mouse, it looks like adding multiple objects:

Problematic scene...

Image on left displays standard scene, image on right displays the problem - I moved the mouse over the scene (only one blue box is expected).

All the meshes disappears when:

  • I save the scene

  • I select item which is displayed in inspector but it wasn't selected before

  • Game is started

When the game is running and I switch to Scene View, the code works as expected: only one mesh in a frame is rendered.

I created simple project for reproducing the error, you can download it here.

To reproduce the problem, follow these steps:

  • Open the project

  • Open scene Assets/Scenes/Scene

  • Open my window: Window / Block Adder

  • Drag and drop Game Object named "Box" to "Template" field in the Block Adder Window

  • Drag and drop Assets/Materials/preview_mat to "Preview material" field in the Block Adder Window

  • Toggle "Enabled" (in the Block Adder Window) to enable the functionality

  • Move the mouse over the scene in Scene View Window.

  • Observe the issue.

My environment:

  • Windows 7 Professional SP1

  • Unity 4.3.0f4 (Free version currently)

littleproject.zip (23.3 kB)
drawmeshproblem.png (61.3 kB)
Comment
Add comment · Show 2
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 guavaman · May 26, 2014 at 09:05 AM 0
Share

Did you ever make any progress on this? I've been having this issue for a while. Initially, I switched to using OnDrawGizmosSelected which does clear the meshes each frame, but has other side effects (such as rendering after OnGUI).

avatar image Aithoneku · May 30, 2014 at 06:49 AM 0
Share

@guavaman I apologize for not answering to you sooner - for some reason, I received e-mail notification about this now, three days later. Anyway, answer is no, but (during work on other project) I found work-around: create game object for this purpose (displaying the mesh and everything) in root of the scene with hide-flags set to hide-and-dont-save (important note: it must be in root, otherwise when scene is saved, any attempt to load the scene will end with crash (it's a Unity bug).

3 Replies

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

Answer by guavaman · May 27, 2014 at 06:13 AM

I found the solution:

MonoBehaviour.OnRenderObject

Make all your Graphics.DrawMeshNow calls from within there and it will work as expected.

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 Aithoneku · May 30, 2014 at 07:10 AM 0
Share

@guavaman I apologize for late reply - see my comment above. Thank you, I can confirm it's working!

Note: with new Unity (currently 4.3.4f1) the behavior is little different: the scene is unchanged during mouse move until you press a button. It can be solved by SceneView.RepaintAll(); and combined with your fix it works well.

avatar image Aithoneku · May 30, 2014 at 07:18 AM 0
Share

Btw. how can I accept this answer? I cannot find the button anywhere...

avatar image drchilitopicoso · Aug 08, 2016 at 12:45 PM 0
Share

I use a separate gameobject, set its hideflags HideAndDontSave and draw in the Update method, but using SetDirty that gameobject everytime i want to refresh. It works fine and you can also use Graphics.Draw$$anonymous$$esh(). The only inconvenience is that it will make your scene dirty and ask you before closing unity if you want to save.

For those that might have thought of checking the source code and search where to hijack the rendering via render textures and so on, don't, there are many things that are hardcoded and will end up in dead ends, internal calls to the C side of Unity and such. I wasted a lot of time searching and in the end it's better to just play inside the Unity box.

avatar image
1

Answer by pvaananen · Jun 28, 2017 at 10:51 AM

Here's a workaround (Unity 5.6.1f1) that allows you to use regular Graphics.DrawMesh instead of DrawMeshNow. It relies on checking when the "frame" (you don't really have the frame loop in editor) changed and submitting new draw calls only then.

 int lastRenderedFrame;
 
 void Start() {
     SceneView.onSceneGUIDelegate += OnSceneGUI;
 }
 
 void OnSceneGUI(SceneView view)
 {
     if (Event.current.type == EventType.Layout)
     {
         // Force the view to update.
         EditorUtility.SetDirty(gameObject);
 
         // Only update if we know that the queue was cleared.
         if (lastRenderedFrame != Time.renderedFrameCount)
         {
             drawMyMeshes(); // Uses Graphics.DrawMesh()
             lastRenderedFrame = Time.renderedFrameCount;
         }
     }
 }
 
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
0

Answer by mustmiekieke · Feb 26 at 01:36 PM

This answer is for people who are running into the same problem but are drawing inside the OnToolGUI() method of an EditorTool!


I am using the new EditorTool clas for creating a custom tool that can place blocks in a grid. I am drawing previews of the blocks with Graphics.DrawMesh() but i was running into similar problems as the OP. I have found many threads discussing this problem but none of the solutions worked for me. That is, until I tried the answer of @pvaananen in this thread. I can't seem to reply directly to his/her comment so I'm posting this here.


So: If you are trying to draw meshes directly inside the OnToolGUI() of an EditorTool, try the answer of @pvaananen! I've replaced the EditorUtility.SetDirty(gameObject); part with EditorUtility.SetDirty(this); and that seems to do the trick.

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

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

21 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 avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Why does my Unity Serialization not work? Do i miss something? 1 Answer

Multiple editor windows combined 0 Answers

Reflection on class variable values null on editor startup 0 Answers

Editor Color Picker issues 0 Answers

How to override geometry of a procedurally generated sprite in Editor Mode 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