Drawing multiple Polygons/Polylines from a single ImmediateModeShapeDrawer does not work

Avatar
  • updated
  • Not a bug

Setup: tiny scene with only a single camera and one ImmediateModeShapeDrawer

Drawer class:

[ExecuteAlways]
public class ShapeDrawer : ImmediateModeShapeDrawer
{
[SerializeField] private List<Shape> _shapes;

private PolygonPath _fillPath;
private PolylinePath _strokePath;

[Serializable]
public struct Shape
{
public bool fill;
public bool stroke;
public Color fillColor;
public Color strokeColor;
public bool closed;
public float lineThickness;
public ThicknessSpace thicknessSpace;
public LineGeometry lineGeometry;
public List<Vector2> points;
}

public override void OnEnable() {
base.OnEnable();

_fillPath = new PolygonPath();
_strokePath = new PolylinePath();
}

public override void OnDisable() {
base.OnDisable();

_fillPath.Dispose();
_strokePath.Dispose();
}

public override void DrawShapes(Camera cam) {
if(_shapes == null || _shapes.Count < 1)
return;

Draw.ResetStyle();
Draw.Matrix = transform.localToWorldMatrix;

int i = 0;
foreach(Shape shape in _shapes) {
if(shape.points == null || shape.points.Count < 1 || (!shape.fill && !shape.stroke)) {
i++;
continue;
}

_fillPath.ClearAllPoints();
_strokePath.ClearAllPoints();

_fillPath.AddPoints(shape.points);
_strokePath.AddPoints(shape.points);

using (Draw.Command(cam)) {
if(shape.fill) {
Dev.Log(gameObject, GetType(), "drawing fill " + i);
Draw.Color = shape.fillColor;

Draw.Polygon(_fillPath);
}

if(shape.stroke) {
Dev.Log(gameObject, GetType(), "drawing stroke " + i);
Draw.Color = shape.strokeColor;
Draw.Thickness = shape.lineThickness;
Draw.ThicknessSpace = shape.thicknessSpace;
Draw.LineGeometry = shape.lineGeometry;

Draw.Polyline(_strokePath, shape.closed, PolylineJoins.Miter);
}
}

i++;
}
}
}

Inspector:

Image 915


Result (should be a white shape w/ black outline, plus another red shape w/ no outline):

Image 916


As you can see, it only ever draws one of each shape.

Reporting a bug? please specify Unity version:
6000.3.5f1
Reporting a bug? please specify Shapes version:
4.5.1
Reporting a bug? please specify Render Pipeline:
Built-in render pipeline
Avatar
Freya Holmér creator
  • Not a bug

There's two things! I'm guessing the second one is the real issue, but

  1. Generally you want to use as few draw commands as possible for performance reasons - ideally just a single Draw.Command(). Moving it to the outer loop here would be much more performant! Or, even better, make a manager class that tracks all your shape objects in the scene, and draws them within the same command
  2. The paths you use for filling/stroking are shared by all shapes in your _shapes list, which means they can't all be drawn independently. The last shape in the list will overwrite the polygon/polyline that the others have yet to draw, before Shapes itself has a chance of drawing them, which I suspect is the cause for only the last path actually rendering. You could fix this by making your Shape type carry polygon/polyline paths as well, but be very careful with it so that you make sure to Dispose() them properly, especially since Shape is a struct
Avatar
Alex Howe

Thanks for the reply! Manager class is a good idea, not sure why I didn't think of that. I did initially have the draw command outside the loop but moved it inside thinking it might fix something 😅