Unity UI SVG support script

SVG in Unity UI

You’ve all be asking so we worked on it and are ready to share at least the first step towards SVG support inside Unity UI. We are sharing the script this way to get it into your hands faster so we can get feedback but it will be included in a future version of the SVG package. This also may not be the final version that gets shipped in the package but it should be pretty close.

Please let us know if you use this and if it works or horribly breaks in some manor such that we can look into why.

As a note Unity UI render mode of “Screen Space - Overlay” does not have AA support, if you need AA to make it really crisp you might want to switch the Canvas to be “Screen Space - Camera”

Usage:
For simple SVG images simply place the SVGImage component on the GameObject.

For a Gradient SVG Image you will need to create a “Gradient” material which has the “Unlit/GradientVector” shader assigned. You can then assign the material to the SVG Image component. You will also have to change the Canvas “Additional Shader Channel” to include “TextCoord2” otherwise the UI system will ignore that data.

3643258–297685–SVGImage.zip (3.05 KB)

15 Likes

Thanks so much for this. I’d love to test this out, but I’m getting some console errors after importing the scripts and folder to an empty 2018.2.6f1 project that has the Vector Graphics package installed.

I believe the SVGImage script is missing the namespace: using UnityEngine.Experimental.Rendering for VertexAttribute, and I’m getting a compilation error that GameObjectUtility does not contain a definition for ‘EnsureUniqueNameForSibling’.

Well ok then I’ll take a look asap to see what’s up. I did build it on 18.3 so maybe there is new apis. Thanks

@Korindian I’ve updated the scripts above. You were 100% right. The one API went from Experimental to non between 18.2 and 18.3 (version i was using). And the other changed name from GetUniqueName to EnsureUniqueName. All should be good now.

Thanks again.

Thanks. Here are my initial impressions (while you were updating the scripts, I just commented out the GameObjectUtility line):

  1. MSAA works if UI camera is set to forward and UI Canvas is set to Screen Space Camera, as you mentioned. However, to get SVGs looking properly round (for example, a 32x32 small svg circle) and not aliased, I need to use 8x MSAA, which really increases required memory. In addition, using MSAA also affects any small point size text (using Text Mesh Pro), which isn’t ideal.

  2. MSAA will not work if there is a scene camera set to deferred, even with a UI camera set to forward, depth only, and the UI set to Screen Space Camera.

  3. For deferred, It is also not possible to use the Post Processing Stack’s AA methods, like FXAA and SMAA (TAA doesn’t work with SVGs) to only affect the UI camera as it will also affect any cameras at a lower depth beneath it. Also these AA options really mess with Text Mesh Pro SDF font rendering in the canvas.

  4. Does this mean that SVGs will have no viable AA in the deferred pipeline?

  5. Would it be possible to do some shader-based antialiasing instead, like how the Asset Store’s SVG Importer and some other assets do?

  6. You may get more people testing this out if posted in the UI forum!

  7. UI SVGs don’t work with Masks.

Edit: Sorry made a few edits to the original post.

2 Likes

@Korindian so in all honesty questions 1-5 I’ll need to leave to the svg guys and will poke them tomorrow to get their opinions. I only really made the AA comment in the initial post as I know a lot of UI users don’t know that AA isn’t supported.

As for question 6 yup that’s the plan but wanted to do small baby steps. It’s cross posted in the main svg forum post so the people that really care might see it first.

As for masks good point I should be able to correct that tomorrow.

Thanks again for taking the initial plunge feed back is invaluable.

2 Likes

Updated the original assets again with the fix for masking SVGs in the UI and some compile defines so i don’t make a mistake of updating the API while testing in 18.3.

@Korindian At this time, we rely on MSAA for edges antialiasing, but as you pointed out, this doesn’t work for with deferred rendering. Antialiasing without MSAA is something we would like to address eventually. You can have a look at the following thread for a discussion of various antialiasing techniques:

We are still in discussion about which antialiasing solutions we should provide. If you have any additional ideas or requirements, let us know!

2 Likes

Thanks for responding. I just perused that thread and it’s great to see Unity’s already been considering various alternatives.

To add some more AA suggestions:

  • Shapes2D, an asset on the Asset Store, recently went open source, so if you’re looking for an example of one blur based approach (see documentation under Anti-Aliasing) implementation of AA, it’s there. I didn’t end up using it for UI as the pixels of the shape tend to snap into place, even with pixel perfect disabled.

  • SVGImporter works in the UI with Screen Space Overlay using its own form of AA.

  • Perhaps having a PPS layer only affect the UI using FXAA or SMAA or TAA, separate from the scene?

  • Noesis GUI from what I remember uses a couple of forms of AA which only affect the UI. It is free to download.

  • I’d be ok with extending boundaries for AA, as mentioned in the other thread, as long as it gives smooth edges and we can plan around the size of the increased borders.

  • The only wish is to have this AA for UI SVGs be separate from text and scene AA so we can tweak as needed.

I’ve been on a long quest to find true resolution independent UI in Unity that’s easy to use and performs well in Unity. It really made me glad to see you guys tackle this with SVGs, and your work is very much appreciated.

Recently I’ve found SDF images are working better than SVGs, with no jaggies, but there are limitations with that as well. It would be great to have a built-in solution that works with AA in deferred though. I really hope you can figure this one out soon. All the best.

3 Likes

Thank you for the exhaustive list, it is very much appreciated!

Hi, I’m having trouble getting a gradient to work. I’ve followed the steps above but no dice. I do see the gradient working properly when I select the top level SVG asset w/the SpriteRenderer so I suspect that the data is fine.

I forgot to mention a step. On the Canvas change the additional shader property’s to include “TextCoord2”.

2 Likes

This is great, been wanting this for a while. It will be nice when you get AA in Screen Space - Overlay. I don’t really like Screen Space - Camera; Also having separate AA for UI instead of using Global MSAA setting.

Great progress so far. Excited for more!

Hi, the sprite is not updated when you set a new value.

public Sprite sprite
{
get { return m_Sprite; }
set
{
if (m_Sprite != value)
{ SetAllDirty();}
}
}

Worked like a charm, thank you so much for this, it’s exactly what I was looking for! Lifesaver!

1 Like

Sorry for the delay the forum wasn’t saying there were new threads. Oh drat your right :(.

Edit: As the SVG package has the script in it now, please download preview.20 and the fix is in there. Thanks for the feedback.

Thanks for getting UI Canvas support working!

We have several full-screen vector art backgrounds that are currently imported as PNG files, which greatly increase our build size. We plan to add more, so we need a better solution.

The current SVG support seems like it’s in good shape except that there is no equivalent to the Image component’s “Set Native Size”.

Our artist currently exports PNG files from Illustrator at the same reference resolution as our Unity Canvas so that we can just import things and hit the “Set Native Size” button. It’s important that we have the same functionality for SVG files, but currently, all SVGs seem to be scaled to a 100x100 box.

The SVG files I’m using right seem to have the required information, but specified in two different ways:

Random SVG from Google:

Adobe Illustrator:

I think sprites should be sized based on the above information, and as a fallback, use the bounds of the SVG’s vertices, and assume the SVG’s units map to Unity UI units.

If a viewbox is specified, it will indeed map to a 100x100 “window size”. I would think the tag’s width and height values should override this, but I’m not sure. We will investigate and fix if necessary.

It is much easier to predict the size of the imported SVG if no viewbox is specified. I think the “responsive” option in the Illustrator SVG export makes it generate a viewbox. Unchecking this option should help.

Also, make sure that the “Preserve Viewport” option in the SVG importer is unchecked. When unchecked, it will generate a sprite sized with the bounding box of the vertices. Otherwise, it will use the bounds specified in the SVG file.

To adjust the size of the sprite, you can play with the “Pixels per Unit” option in the SVG importer. It acts as a “divisor” on the coordinates specified in the SVG file.

I’ll also have a look to see if we can adapt “SetNativeSize” to work with SVG Images.

Hope this helps :slight_smile:

This fixed it. The Sprite Editor’s “W” and “H” now show the correct size.

I tried fixing up SVGImageEditor.cs to display the builtin “Set Native Size” button, but Graphic.SetNativeSize seems to have no effect. I implemented it myself using (rectTransform.sizeDelta = sprite.rect.size).

At this point, I can import small simple elements and size them correctly, but I tried to import a large complex SVG, and the result was a mess. The image displayed correctly in the Sprite Editor, but in the scene, it was just a jumble of random colors. The image does contain gradients, but I don’t think that fully explains what I’m seeing. The imported SVG asset also has a second child (***Atlas), but I have no idea where that came from. I’ve sent the image via PM.

Thanks again =D

1 Like

It turns out it was the gradients. Following these two steps fixed it:

  1. Make sure the SVG Image has a material that uses the “Unlit/VectorGradient” shader
  2. Make sure that the Canvas has “TexCoord2” in the “Additional Shader Channels”

Thanks!

1 Like