Hi there!
I’m using the built-in render pipeline. Recently found that pretty much all of my custom editor tools are visually broken in Unity 2021 and up. After a few days spent debugging this, the culprit seems to be Graphics.DrawMeshNow. Conceptually, this is the issue:
mesh.colors = redColors;
Graphics.DrawMeshNow(mesh);
mesh.colors = greenColors;
Graphics.DrawMeshNow(mesh);
//Mesh is drawn twice, using greenColors for both.
Expected result: the mesh is rendered twice, once red and once green (Unity 2019.4 and older):
Result: the mesh is rendered twice, both times green (same code, Unity 2021.3.0f1 and up, haven’t tested versions in-between):
What-the-heck. Seems like DrawMeshNow is somehow caching the mesh, instead of rendering it immediately. This used to work fine in all previous Unity versions. I’m starting to doubt the reliability of very basic stuff in Unity, which is kinda frustrating.
Here’s the actual code I’m using to test this:
using UnityEngine;
public class DrawMeshNowBug : MonoBehaviour
{
Material paintMaterial;
public Mesh mesh;
Mesh copy;
// Start is called before the first frame update
void Start()
{
paintMaterial = Resources.Load<Material>("VertexColorMaterial");
copy = GameObject.Instantiate(mesh);
}
private void OnDestroy()
{
Destroy(copy);
}
// Update is called once per frame
public void OnPostRender()
{
if (paintMaterial.SetPass(0))
{
Color[] colors = new Color[copy.vertexCount];
for (int i = 0; i < colors.Length; i++)
colors[i] = Color.red;
copy.colors = colors;
Graphics.DrawMeshNow(copy, Matrix4x4.identity);
for (int i = 0; i < colors.Length; i++)
colors[i] = Color.green;
copy.colors = colors;
Graphics.DrawMeshNow(copy, Matrix4x4.Translate(Vector3.right));
}
}
}
This is the shader used for flat vertex color rendering (built-in pipeline), which imho is as simple as it gets:
Pass {
Cull Back
Fog { Mode Off }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct vin{
float4 vertex : POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
struct v2f {
float4 pos: POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
sampler2D _MainTex;
v2f vert(vin v) {
v2f o;
o.pos = UnityObjectToClipPos (v.vertex);
o.texcoord = v.texcoord;
o.color = v.color;
return o;
}
fixed4 frag(v2f i) : SV_Target {
return i.color;
}
ENDCG
}
Just a sanity check before I submit a proper bug report: am I doing something wrong here, or misinterpreted the way DrawMeshNow is supposed to work?
Edit: generalized this to multiple DrawMeshNow calls in a row, modifying the mesh in-between calls: mesh data is indeed cached, only the very last form of the mesh is rendered multiple times.
The only workaround I found is to create a separate mesh for each DrawMeshNow call. Reporting this as a bug.