Categories
Unity3D Unity3D-tips

#unity3d #missingdocs: CanvasRenderer.SetMesh() – making it work (mostly)

This once-obscure method, that – I guess – is the low-level call used by most of the new Unity GUI … is now the only way of drawing meshes in GUIs. The previous options have been removed, with brief comments telling you to use .SetMesh instead. Half of the DrawMesh / DrawMeshNow methods have also been removed (no explanation given in docs), which were my other go-to approach.

Unfortunately, no-one has documented SetMesh, and it has significant bugs, and breaks with core Unity conventions. This makes it rather difficult to use. Here’s the docs I’ve worked out by trial and error…

CanvasRenderer.SetMesh

The minimum for this method to work is:

  1. A Canvas in mode “Screenspace: Camera”
  2. A child object with:
    1. A mesh (that must be hundreds of meters wide/tall)
    2. A material (see below. Not optional!)
    3. A CanvasRenderer

Usage

Mesh bounds are ignored; if CanvasRenderer had been designed to render meshes to canvases, it would use this method – but as noted above, I believe it was designed for something completely different: it’s a low-level helped method rathe than a user-facing API method.

Instead, your mesh will be rendered at the Canvas’s own pixels/meter scaling (a scale of 1 meter = 1 pixel by default). In the Editor, this will make it appear very large, but it will render correctly on your cameras.

Current bugs

CanvasRenderer frequently deletes the mesh, but has no method (public or private) to detect when the Mesh has been deleted so you can re-create it. It deletes when you enter or exit play mode, but after that it seems to leave it alone. There is a hidden delegate inside the class that appears to let you react to this – but it’s not public and I don’t know how to use it (yet).

Unlike all rendering elsewhere in Unity, if there is no material, this method will silently fail, and will NOT render a magenta object. This makes debugging misleading and difficult.

In “Screenspace: Overlay” mode it seems to be broken; not only does nothing render, but it doesn’t even render in the Editor, suggesting to me that it’s disabled. I couldn’t find a combination that worked.

You cannot set/add a material to this object using standard Unity approach, instead you must first alter the value of materialCount to the number of materials you intend to have on the mesh, or it will crash. The docs tell you to use a non-existent method – don’t worry, simply alter the property directly (this works).

EnableRectClipping doesn’t work at all – this is a serious problem if you’re using this method to draw 3D objects inside a 2D layout-managed GUI. As mentioned above, I think it was either never intended to be used, or there was a mixup and people forgot that it’s a low-level method, and not an API method.