Search Unity

Question I want to draw a 2D grid on top of my ground meshes, is this the right way?

Discussion in 'General Graphics' started by ankurs3thi, Mar 22, 2021.

  1. ankurs3thi

    ankurs3thi

    Joined:
    Feb 13, 2021
    Posts:
    4
    Hey folks!

    I'm building a tactical game with Unity, with mechanics similar to Advance Wars or Fire Emblem. Similar to those games, I want to draw a 2D grid on the ground indicating a friendly unit's movement range when the player clicks on it. Something like this image.

    Currently, I'm drawing this grid by procedurally generating a bunch of quads on top of my ground meshes and applying a transparent green material to them.

    However, I'm running into two issues with my method:
    1. I can't figure out how to draw borders around my grid cells. Do I use a shader? A texture? Something else? I'm new to Unity and graphics programming, so I don't even know what to search for.
    2. Some of my ground meshes are not entirely flat, so bits of them poke out of my grid.
    Am I approaching this problem correctly, or should I throw out the code I currently have and start from scratch with a different approach?

    Thanks for reading.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Sure. Either one works. You can make a solid white texture that's semi-transparent with the center slightly more semi-transparent and you'd be done. Something like the built Particles/StandardUnlit shader should work without any other changes.

    If you wanted to use a custom shader that draws a box ... well ... that's also possible. But that's jumping a bit into the deep end. Drawing an outlined box using a procedural SDF in a shader isn't particularly difficult, but you need to learn the rest of the basics of shader writing to get there. Possible, but not really necessary if a static texture gets you everything you need.

    If you look at the screenshot you gave as your example, they have the same problem. The grid squares around the sides are intersecting slightly with the ground mesh. And the grid squares on the "stairs" (textured ramp) are pulled up so they're going through the mid calf of the characters standing in those spots. Those characters are also floating above the stairs a bit too, and their shadow is slicing right into the geometry. But basically their solution was to keep the grid floating above the ground by some amount.

    Other options would be to render the ground grid as a projection of some kind onto the ground. Unity's built in projector component would do what you want, but they're very slow, especially if you're going to have so many projecting onto a single mesh as they work by re-rendering the entire mesh again for each projector. That gets expensive fast, especially with large meshes. Plus there aren't any build in projector shaders that will render the way you need. If you want to go the projector route, you might look into a decal rendering system from the asset store.

    The biggest problem with projected decals is ... well ... they conform to the ground. If you have lumpy terrain it might be difficult to really see the cells.


    Another option, one that requires a custom shader as well, would be to render them using a transparent shader that renders during the opaque queue after the ground but before the characters and uses
    ZTest Always
    and
    ZWrite Off
    . The idea would be to assign all of the terrain materials a custom render queue so they render first. Then if you render with a shader with
    ZTest Always
    it'll always render on top of everything ignoring intersections. Using
    ZWrite Off
    will ensure things that render afterward don't intersect with the transparent planes, but instead always on top of those, at least where objects are rendered closer than the terrain. Then all objects you want to render over the grid needs to have a queue higher than the grid quads. The effect will be the grid will be "flat", not intersect with the ground, and characters standing on top will won't intersect with the quads and can appear to be standing on the ground.
     
    ankurs3thi likes this.
  3. ankurs3thi

    ankurs3thi

    Joined:
    Feb 13, 2021
    Posts:
    4
    Thanks for this detailed reply bgolus! This helps a lot.

    I want to stick with my procedurally generated meshes, and apply a texture to them to get those borders. However, I'm having a bit of trouble with doing that.

    I created a new 64x64 PNG that was all white. The center of the PNG had an opacity of about 0.5 and the border had an opacity of 0.8. I then imported this into Unity and added it to my material's Base Map property. When I ran the game, I noticed no change in how my grid looked.

    I'm using Unity 2020.2.7f1 with URP. My material is using the Universal Render Pipeline/Lit shader.

    Do I need to play around with the tiling and offset parameters? How do I calculate those values? As I said, my PNG is 64x64 px and the quads I'm applying the texture to are 1.25 x 1.25 world units. Is my PNG simply too small? Or am I missing an important setting somewhere?

    Once again, thanks a bunch for taking the time to reply. This really helped!
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    By default the Lit shader is always opaque and ignores the texture's alpha (or which you can use to drive the material's Smoothness instead of needing a separate Metallic texture). You need to change its Surface Type to Transparent. A Blending Mode option should then appear that defaults to Alpha, which you probably want to leave it at.
     
  5. ankurs3thi

    ankurs3thi

    Joined:
    Feb 13, 2021
    Posts:
    4
    It took me a while to figure out, but after a lot of head-scratching I discovered what I was doing wrong: while my code for creating the quad meshes was correct, I was forgetting to set their
    uv
    . After setting the
    uv
    correctly, my grid texture started showing up just as I wanted!

    Thanks for pointing me in the right direction, @bgolus!