1

My goal is to draw simple, colored meshes on a Canvas in Unity. I set up a Canvas and chose Render Mode World Space. I then added a GameObject, set its RectTransform, added a CanvasRenderer (later also a MeshFilter and MeshRenderer) and a script to create my mesh. Creating the mesh works fine but i have to major problems. The first is that the lightning does not work correctly when using CanvasRenderer instead of MeshRenderer: This image uses the MeshRenderer and is how it should look like This image uses the CanvasRendere

My second problem is that no matter the order in the hierarchy as soon as i add a second object to my canvas (e.g. an image with the color white) my custom mesh and its color are no longer visible. Only the white image.

Here is the script i used. The last few lines are comments or not based on what Renderer i tried.

using UnityEngine;

public class MeshCanvas : MonoBehaviour
{
    public Material material;
    
    Mesh mesh;
    Vector3[] vertices;
    int[] triangles;

    float canvasHeigt;
    float canvasWidth;

    private void Update()
    {
        canvasHeigt = FindObjectOfType<Canvas>().GetComponent<RectTransform>().rect.height;
        canvasWidth = FindObjectOfType<Canvas>().GetComponent<RectTransform>().rect.width;

        vertices = new Vector3[]
        {
            new Vector3(0, 0),
            new Vector3(0, canvasHeigt),
            new Vector3(canvasWidth, canvasHeigt),
            new Vector3(canvasWidth, 0)
        };

        triangles = new int[]
        {
            0, 1, 2,
            2, 3, 0
        };

        mesh = new Mesh();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.RecalculateNormals();

        /*
        this.GetComponent<MeshFilter>().mesh = mesh;
        this.GetComponent<MeshRenderer>().material = material;
        */
        
        CanvasRenderer cr = this.GetComponent<CanvasRenderer>();
        cr.SetColor(Color.black);
        cr.materialCount = 1;
        cr.SetMaterial(material, 0);
        cr.SetMesh(mesh);
        
    }
}
ZoKi Mo
  • 51
  • 1
  • 5

1 Answers1

2

For problem 1: If you just want a normal unlit UI element, you should be using the UI/Default material, not a Standard material. If you do want lighting, In your Canvas properties, set 'Additional Shader Channels' to 'Everything'. Otherwise lighting will not be calculated correctly. You can use a Standard material in this case, or one of the UI/Lit materials.

As for problem 2, I'm not sure. Unity batches all UI elements together for performance reasons, so maybe setting the mesh directly on the CanvasRenderer is breaking the batching, or maybe it's to do with the material you're using.

If you just want to be able to add your own custom 2D shapes to a Canvas, the better way is to make a class that derives from Graphic or MaskableGraphic and override the OnPopulateMesh method to provide your custom mesh vertices. The advantages here are that it will behave like any other UI element with all the same parameters etc. and you can add it to the Create GameObject menus to easily add it to your scene.

Cadmonkey33
  • 181
  • 1
  • 5
  • I work with OnPopulateMesh now. You were right it makes things much easier except the fact that it is poorly documented in my eyes... – ZoKi Mo Jan 28 '23 at 15:12