Bug - Poor Performance of AssertNotRendering() when drawing in play mode in the editor

  • ALINE version: 1.7.8
  • Unity version: 6000.0.60f1
  • Render pipeline: URP

There is a performance issue when using ALINE to draw lines in game while in the editor.

However in editor each line drawn results in a call to CommandBuilder.AssertNotRendering(), which pulls stack traces if not called in the OnDrawGizmos function. However we are using LateUpdate so this fires on each line drawn and causes a frame spike. It’s compiled out in builds but is very annoying when testing in the editor!

Suggest this check is skipped when using Draw.ingame.

Hi.

Can you show your code? It shouldn’t be doing that on every line.

Sure, here is a simplified version of what I’m doing:

    public void LateUpdate()
    {
        for (int i = 0; i < grid.edges.Length; i++)
        {
            var edge = grid.edges[i];

            var a = grid.vertexPositions[edge.a];
            var b = grid.vertexPositions[edge.b];
            Draw.ingame.Line(a, b, Color.black.SetAlpha(0.2f));
        }
    }

There are about 2000 edges to draw, which performs fine on most frames. However, because I’m doing this in LateUpdate instead of OnDrawGizmos, this function fires every 128 frames:

		static void AssertNotRendering () {
			// Some checking to see if drawing is being done from inside OnDrawGizmos
			// This check is relatively fast (about 0.05 ms), but we still do it only every 128th frame for performance reasons
			if (!GizmoContext.drawingGizmos && !JobsUtility.IsExecutingJob && (Time.renderedFrameCount & 127) == 0) {
				// Inspect the stack-trace to be able to provide more helpful error messages
				var st = StackTraceUtility.ExtractStackTrace();
				if (st.Contains("OnDrawGizmos")) {
					throw new System.Exception("You are trying to use Draw.* functions from within Unity's OnDrawGizmos function. Use this package's gizmo callbacks instead (see the documentation).");
				}
			}
		}

The problem is the call to StackTraceUtility.ExtractStackTrace() firing 2000 times, which is quite slow and generates large amounts of garbage.

Hi

Are you sure that’s the code that’s causing this?

The check is only done the first time a CommandBuilder is used every frame. So it should only happen once per frame for the Draw.ingame builder.

The only case when it can happen multiple times is when doing things like this:

var ingame = Draw.ingame;
var ingame2 = ingame; // Copies the struct since it's not by ref
ingame.Line(...);
ingame2.Line(...);

as the first .Line call will not update the second CommandBuilder struct, so it will perform its initialization step again. (both lines will still be drawn, it just a bit more checking).

Ah thanks - fixed it. I was wrapping the Draw.ingame.Line function with my own that was not passing the ingame builder by reference.

1 Like