Unity Tutorial - Working with SVG files Featured

Unity Tutorial: Learn how to use SVG in Unity

Support for SVG in Unity is quite limited, and the documentation is not particularly useful. In this tutorial, I’ll guide you thru the process of importing SVG in Unity projects, both from the Unity Editor and dynamically via code.

Importing the SVG package

The first thing we need to do to be able to work with SVG files in Unity, is to import the Unity Vector Graphics package from the Package Manager. In the Unity Editor, Windows -> Package Manager, and make sure to select “Unity Registry” from the “Packages” dropdown:

Unity Tutorial - Importing SVG - Import Vector Graphics package

Notice that at the time of writing this post, the Vector Graphics package is still marked as Experimental, which means that it’s not code-complete, might contain bugs, and there’s even a chance that it will be scrapped.

If the “Vector Graphics” package is not listed, make sure you’ve enabled support for pre-released packages in your project settings. In the Unity Editor, Edit -> Project Settings, select the “Package Manager” item on the left, and check the “Enable Pre-release Packages” checkbox:

Unity Tutorial - Importing SVG- Enable pre-release packages

Importing SVG from the Unity Editor

Importing an SVG file to Unity is extremely simple – just add the SVG file to your assets folder and let the Vector Graphics package do its work. You can select how the graphics will be imported based on its usage:

Importing SVG file by code

When importing by code, we first need to retrieve the SVG content. For the sake of simplicity, we’ll use a string property.

public string svg = "...";

To load the content of the SVG, we’ll create a StringReader to read our string (we can also use a StreamReader if we have the SVG content as a Stream object). Then, we’ll pass the reader to SVGParser.ImportSVG method:

using StringReader textReader = new StringReader(svg);
var sceneInfo = SVGParser.ImportSVG(textReader);

This gives us a SceneInfo object which contains all the graphic details, and which can start working with. To render the vector graphics elements on screen, first get a tessellated (triangulated) version of the scene. We can tessellate our SceneInfo object using the VectorUtils.TessellateScene method:

var geometries = VectorUtils.TessellateScene(sceneInfo.Scene, new VectorUtils.TessellationOptions
        {
            StepDistance = 10,
            SamplingStepSize = 100,
            MaxCordDeviation = 0.5f,
            MaxTanAngleDeviation = 0.1f
        });

Now that we’re finished importing the SVG to Unity, and we have our graphics as a collection of geometries, we can decide how we’d like to work with them – as a Sprite or as a Mesh. Let’s create a base script to allow us to demonstrate the various methods:

public class BaseSvgScript : MonoBehaviour
{
    [Multiline()]
    public string svg = "";
    public int pixelsPerUnit;
    public bool flipYAxis;

    protected List<VectorUtils.Geometry> GetGeometries()
    {
        using var textReader = new StringReader(svg);
        var sceneInfo = SVGParser.ImportSVG(textReader);

        return VectorUtils.TessellateScene(sceneInfo.Scene, new VectorUtils.TessellationOptions
        {
            StepDistance = 10,
            SamplingStepSize = 100,
            MaxCordDeviation = 0.5f,
            MaxTanAngleDeviation = 0.1f
        });
    }
}

Import as a Sprite

When importing as a Sprite, we can just call the VectorUtils.BuildSprite method to build our Sprite object from our geometries. We can then use a SpriteRenderer component to render the graphics. Here’s our sample script, our GameObject components, and the expected result:

[RequireComponent(typeof(SpriteRenderer))]
public class SpriteSvgScript : BaseSvgScript
{
    void Start()
    {
        List<VectorUtils.Geometry> geometries = GetGeometries();

        var sprite = VectorUtils.BuildSprite(geometries, pixelsPerUnit, VectorUtils.Alignment.Center, Vector2.zero, 128, flipYAxis);
        GetComponent<SpriteRenderer>().sprite = sprite;
    }
}

Importing as a Mesh

An alternative to importing the SVG as a Sprite, is to load is as a Mesh. For that, we’ll need a MeshFilter and a MeshRenderer. We can then use the VectorUtils.FillMesh method to create the mesh from the geometries. Once again, here’s our sample script and GameObject components (the results are expected to be the same):

[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class MeshSvgScript : BaseSvgScript
{
    void Start()
    {
        List<VectorUtils.Geometry> geometries = GetGeometries();

        var meshFilter = GetComponent<MeshFilter>();
        Mesh mesh = meshFilter.mesh;

        VectorUtils.FillMesh(mesh, geometries, pixelsPerUnit, flipYAxis);

        var meshRenderer = GetComponent<MeshRenderer>();
        meshRenderer.materials = new Material[] { new Material(Shader.Find("UI/Default")) };
    }
}
Unity Tutorial - Importing SVG - Import as Sprite Components

You can download the source code for this tutorial from https://gist.github.com/saguiitay/fdc86365ffb4ee7aa9c7b5e27afc9707

While you can use the above code in your project, you might want to use one of the assets below from the Unity Asset Store to speed-up your work, and enjoy enhanced features:

SVG FAQ

What is SVG?

SVG stands for Scalable Vector Graphics. It is a vector graphics format intended primarily for the Web, though it is getting wider deployment on a variety of devices. Vector graphics are a way of describing an image not as rows and columns of pixels, but as a set of instructions on how to create the image. A raster image, such as a bitmap, PNG, JPEG, or GIF, is merely a series of unconnected pixels (or colored dots), while a vector image represents various parts of the image as discrete objects, so it allows for better interactivity. When you zoom in on a raster image, it becomes blocky and fuzzy (or “pixelated”), but when you zoom in on a vector image, it remains crisp and clear at any resolution.
Also, vector graphics can often have a smaller file size (especially when compressed) than the equivalent raster image. Note that for photographic images, however, raster images are called for; vector graphics are better for line art, drawings, charts and graphs, maps, and text.

Why use vector images instead of bitmap images?

Because vector images are made up of points and lines, they can be scaled without any loss of image quality. This is because your computer is using the information in each geometric primitive to draw the image, instead of displaying a set pixel map. When bitmap images are scaled up, they become fuzzy, but when vector images are scaled up they remain crisp.

How are vector images constructed?

A vector image is generated from discrete points and vector data attached to those points. These vectors, in combination with their relationship to other points and their vectors, define a path. The path follows a curve defined by the magnitude and direction of the vectors of its two endpoints. This path is given a stroke that acts as a border or a fill, or both.

Does Unity Support SVG

Unity has native support for SVG (Scalable Vector Graphics) files via the Unity Vector Graphics package available from the Unity Package Manager. It can be used to import SVG to Unity as sprites, or as vectors.

GET NOTIFIED

Sign up to receive notifications when a new Unity Asset is released.