Been struggling with this for a while now. I need to draw a mesh using Graphics.DrawMesh, not Graphics.DrawMeshNow as I want lighting information. The problem is "Update" is only called when the scene changes. As a result, my mesh disappears under certain situations, like: - Losing application focus: e.g: toggling between Unity and Visual Studio. - Randomly after script reloads - Focusing on an object, sometimes unity clears graphics when doing this but doesn't call Update after. I know I can't use: OnRenderObject, DrawGizmos, EditorApplication.update. Because these are called many times before unity actually performs scene rendering. Drawing a mesh in OnWillRenderObject crashes Unity. So my question is: How can I tell Unity to render the scene, or clear the graphics in edit mode? As an example, imagine a cube that is rendered in-front of the scene camera that needs to react to light. In order to do this, I need an event that updates frequently, has access to Camera.current and only draws before the scene is about to be rendered. The object/script responsible for drawing cannot be added to the camera. The object/script cannot be made dirty when the scene camera moves: i.e don't modify the scene in any way. I think this scenario is impossible with Graphics.DrawMesh. But just wanted to check if there is a possible solution. I might be able to try CommandBuffers, but that's a whole other beast, especially if you want Cast/Receive shadows. The endless struggle continues...
I had a very similar question and the 'trick' i was told is to use DrawMeshInstanced and that worked indeed. (https://forum.unity3d.com/threads/how-to-graphics-drawmesh-in-editor-sceneview.443572/)
Thanks for the response. Been playing around with this more. Turns out you can just set the material to use instancing. However, there's some extra weirdness going on: Code (CSharp): using UnityEditor; using UnityEngine; [ExecuteInEditMode] public class GraphicsTest : MonoBehaviour { public Mesh mesh; public Material material; private void OnEnable() { UnityEditor.SceneView.onSceneGUIDelegate -= OnSceneGUI; UnityEditor.SceneView.onSceneGUIDelegate += OnSceneGUI; } private void OnDisable() { UnityEditor.SceneView.onSceneGUIDelegate -= OnSceneGUI; } private void OnSceneGUI(SceneView sceneView) { Draw(sceneView.camera); } private void Update() { Draw(Camera.main); } private void Draw(Camera camera) { if (mesh && material && camera) { Matrix4x4 matrix = camera.transform.localToWorldMatrix * Matrix4x4.TRS(Vector3.forward * 10, Quaternion.identity, Vector3.one); //For some reason, this stops Unity from piling up the draw commands? material.enableInstancing = true; //No trail, object visible twice in scene, scene mesh visible in game. Graphics.DrawMesh(mesh, matrix, material, gameObject.layer, null); //Leaves a small trail, object only visible in camera //Graphics.DrawMesh(mesh, matrix, material, gameObject.layer, camera); } } } If I draw the mesh without supplying a Camera to render to, the mesh is drawn twice in the scene and in the game, this is expected because the Docs state passing null here draws the mesh in every camera. Ok, so I want to just draw the mesh in the camera supplied. Cool, oh wait... It leaves a small trail of meshes before clearing itself. Setting the material to a transparent type, shows that the mesh is drawn multiple times before being cleared. Very strange. OnRenderObject seems unusable, supplying the camera to DrawMesh in OnRenderObject results in no mesh being drawn. I suspect this is because rendering has already occured, so the mesh is queued for the next run, but the camera clears everything before it even gets drawn next time. Anyone got any ideas as to why the mesh would be drawn multiple times with an instanced material? Or even why instancing works in this case? Why does a non-instanced material leave an infinite trail meshes, but an instanced one leaves only a small trail of meshes. None of this makes any sense. I tried looking into Command Buffers, but that was a total fail, trying to draw a mesh with a Command Buffer with lighting seems to be reserved for people with graphics chips in their brains. Such a simple thing made unnecessarily difficult.
Ok, I think I figured it out. By using a flag telling the object to render, I can limit it to render once OnSceneGUI Code (CSharp): using UnityEditor; using UnityEngine; [ExecuteInEditMode] public class GraphicsTest : MonoBehaviour { public Mesh mesh; public Material material; private bool render; private void OnEnable() { UnityEditor.SceneView.onSceneGUIDelegate -= OnSceneGUI; UnityEditor.SceneView.onSceneGUIDelegate += OnSceneGUI; } private void OnDisable() { UnityEditor.SceneView.onSceneGUIDelegate -= OnSceneGUI; } private void OnSceneGUI(SceneView sceneView) { if (render) { render = false; Draw(sceneView.camera, sceneView.camera.transform.localToWorldMatrix * Matrix4x4.TRS(Vector3.forward * 10, Quaternion.identity, Vector3.one)); } } /* This causes object to be rendered twice when playing private void OnRenderObject() { render = true; } */ private void OnDrawGizmos() { render = true; } private void Update() { Draw(Camera.main, Matrix4x4.identity); } private void Draw(Camera camera, Matrix4x4 matrix) { if (mesh && material && camera) { Graphics.DrawMesh(mesh, matrix, material, gameObject.layer, camera); } } } In the above code, the scene mesh is drawn at the scene camera (albeit a little laggy behind, but that's ok) and is not visible in the game camera. The same occurs for the game camera, mesh is drawn at 0,0,0 in the game view No need for instancing either! Seems that using OnRenderObject was setting the "render" flag to true more than once. Could probably fix that by checking the current camera, but OnDrawGizmos works out-of-the box
Ok, this is the one, simple and works much better Code (CSharp): using UnityEditor; using UnityEngine; [ExecuteInEditMode] public class GraphicsTest : MonoBehaviour { public Mesh mesh; public Material material; private void OnEnable() { Camera.onPreCull -= DrawWithCamera; Camera.onPreCull += DrawWithCamera; } private void OnDisable() { Camera.onPreCull -= DrawWithCamera; } private void DrawWithCamera(Camera camera) { if (camera) { Draw(camera, camera.transform.localToWorldMatrix * Matrix4x4.TRS(Vector3.forward * 10, Quaternion.identity, Vector3.one)); } } private void Draw(Camera camera, Matrix4x4 matrix) { if (mesh && material) { Graphics.DrawMesh(mesh, matrix, material, gameObject.layer, camera); } } } No idea when those Camera events became a thing, but very thankful for them
Logged in to say thank you for this. I had a hacky mess with Repaint events, OnSceneGui and Update to render my meshes into Scene and GameView and this works much better.