Terrible performance in comparison to vanilla Gizmos

I’m trying to switch from using Unity’s Gizmos to ALINE.

The Unity Gizmos code which looks like this:

foreach (Region region in RegionManager.Regions.Values)
        {
            Gizmos.color = Color.green;
            foreach (Vector3Int node in region.Nodes)
            {
                Gizmos.DrawWireCube(new Vector3(node.x, node.y, 0), new Vector3(1, 1, 1));
            }
        
            Gizmos.color = Color.red;
            Gizmos.DrawWireCube(new Vector3(region.Rect.center.x - 0.5f, region.Rect.center.y - 0.5f, 0), new Vector3(region.Rect.width, region.Rect.height, 1));
        }

Results in this performance (and preview):

However, the equivalent code of ALINE:

foreach (Region region in RegionManager.Regions.Values)
        {
            foreach (Vector3Int node in region.Nodes)
            {
                Draw.WireRectangle(new float3(node.x, node.y, 0), Quaternion.Euler(-90, 0, 0), new float2(1, 1), Color.green);
            }
        
            Draw.WireRectangle(new float3(region.Rect.center.x - 0.5f, region.Rect.center.y - 0.5f, 0), Quaternion.Euler(-90, 0, 0), new float2(region.Rect.width, region
                .Rect.height), Color.red);
        }

Results in this performance (and preview):

That’s almost 4x the difference and I have no idea what I’m doing wrong. I know it’s not optimal to be drawing this many things for debugging, but I’ll require similar functionality in-game too (when I’ll be using Draw.ingame.something). How can I fix this?

Additionally, I’ve noticed (and you can see this in the images) that the Unity gizmos when zooming out start fading away and getting thinner (as they should), but ALINE rectangles seem to keep this “minimum thickness” and you can see the entire map is very green compared to Unity gizmos. How can I fix this? I want the lines to remain small when the player zooms out the camera.

Hi

Would you mind checking the unity profiler to see what is taking up all the cpu time?

Hey

Here’s the profiler view when I enable that specific ALINE code:

Thanks!

I replicated the results and the performance was indeed pretty bad.
It is due to several things:

  1. Your Quaternion.Euler(-90, 0, 0) call is pretty slow, you should move it outside the loop.
  2. You assigned the color for each rect instead of making a scope (Documentation). When you have that many things to draw, the small overhead adds up.
  3. The WireRectangle is not a primitive in ALINE. Instead, it will just draw 4 lines in the C# code. I’ve changed this in my dev version now which improves performance quite a lot.
  4. ALINE’s performance can of course be improved in general. You might be glad to know that I’ve made some other changes to how lines are drawn in ALINE to make it even faster. See the screenshot below for a comparison with your use case. The improvements will be included in the next update (due in the next few days).
public override void DrawGizmos () {
    // Caching this field avoids a tiny bit of overhead
    var draw = Draw.editor;
    // Caching the quaternion is important as this calculation
    // is pretty slow and involves a lot of trigonometry.
    var rot = Quaternion.Euler(-90, 0, 0);

    for (int x = 0; x < 180; x++) {
        // Using a scope is more efficient than specifying the color each time
        using (Draw.WithColor(Color.green)) {
            for (int y = 0; y < 180; y++) {
                draw.WirePlane(new float3(x, y, 0), rot, new float2(2, 2));
            }
        }
    }
}

If you want to make the lines transparent as the camera moves further away, then you can adjust the color that you draw the lines with. There is nothing built-in for this at the moment, I’m afraid.

One other reason that your lines look very green is that you are drawing two lines on top of each other everywhere. Each tile draws a rectangle, so each tile edge gets covered twice.

If you just want to draw a grid where each tile has the same color, I’d recommend Draw.WireGrid (which will also be significantly faster than your current approach).

Hey Aron. Thanks for the detailed and fast reply.

I’ve implemented all the suggestions you mentioned; moved the Quaternion outside the loop, used a scope for color, changed WireRectangle to WirePlane (I can’t use WireGrid because on a 100x100 map, some tiles will have rectangles on them and some won’t, and AFAIK WireGrid would draw on all 100x100 without the ability to exclude some tiles). The new code now looks like this:

var draw = Draw.editor;
        var rot = Quaternion.Euler(-90, 0, 0);

        using (Draw.WithColor(Color.green))
        {
            foreach (Region region in RegionManager.Regions.Values)
            {
                foreach (Vector3Int node in region.Nodes)
                {
                    draw.WirePlane(new float3(node.x, node.y, 0), rot, new float2(1, 1));
                }

                draw.WirePlane(new float3(region.Rect.center.x - 0.5f, region.Rect.center.y - 0.5f, 0), Quaternion.Euler(-90, 0, 0), new float2(region.Rect.width, region
                    .Rect.height), Color.red);
            }
        }

However, from the previous 20FPS, I now get 28FPS which isn’t a significant improvement. I’m pretty sure I did everything correct, so is it possible that your new update for ALINE can improve performance by that high of a margin?

I’d appreciate if you could let me know when the update comes out so I can see if things got better.

Thanks a lot!

Hi

The new update is out now (version 1.5). Try it out and let me know how it works.

Btw. Foreach loops are also slower than regular for loops. I don’t think it makes much of a difference in this case, but you should consider it if you want better performance.

Hey

I’ve installed the new update and there one huge issue - suddenly, none of the ALINE gizmos are showing. I haven’t even changed the previous working code and restarted my editor several times to make sure it’s not something on my end.

However, when I do try to activate them, now I get about 60 FPS, where before I would get about 28, which is about 2x of an improvement, but still a bit lacking compared to Unity gizmos with which I get about 80FPS.

Any ideas what would be causing me not to see the gizmos?

Also, this is the profiler view:

Ouch. I was worried that would happen for some users.
Essentially, in the latest update, I used more advanced shader features. Most graphics cards from the past 10 years or so should support them, I think, but there are no reliable statistics that I’ve found.
What is your graphics card, platform and which graphics api are you using (this is set in the Unity player settings)? Also, do you think you can click on the aline_outline shader and see if any warnings show up?

I’ll probably publish an update to ALINE that reverts this change later today. This will make things slower again, but the gizmos will be visible at least.

If you have the time, you could help me debug the issue you are having with 1.5.0 by not upgrading to 1.5.1.

My graphics card is Nvidia GTX 1060 6GB VRAM. I’m on Windows 11 and pretty sure I’m using Direct3D11. I’m not sure where to find this aline_outline shader. I have time and I can help you debug, tell me how else I can help you. I’d always prefer speed, so it’d be helpful if we could debug and figure this out.

Yeah that should definitely be supported. Weird.
You can find the outline shader in Packages/ALINE/Resources

Certainly weird. No errors or warnings seem to show up when I click on the shader.


Do you use any other non-default graphics settings? E.g. a render pipeline.

Pretty sure everything should be standard. I switched from 2D render pipeline to the standard one recently.

Screenshot_2
Screenshot_1

Hm. Could you try disabling the render pipeline and just use the built-in one?

I’m not sure if I’m doing it correctly, but following this guide I’ve switched Quality → Rendering to None and Graphics → Scriptable Render Pipeline Settings to None (which should switch me back to the built in pipeline) and there is no difference. I still can’t see ALINE rendering gizmos.

Hmm. Very strange. Would it be possible for you to open a new empty unity project (without using a render pipeline), import ALINE and see if the example scenes work there? You can’t download 1.5.0 anymore, but you can copy your package from your existing project’s Library/PackageCache folder. Just copy ALINE into the new empty project’s Assets folder.

Opened a new 2D project with the built in pipeline, copied over ALINE and all 4 example scenes seem to be working perfectly. So, it seems like this has something to do with the URP?

Weird.

Well, you said you disabled URP in your original project and it still didn’t work. So I’m not so sure about that.

Would it be possible for you to share your project with me?

Sure. I’ll send it to you in DMs