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:
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:
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")) };
}
}
You can download the source code for this tutorial from https://gist.github.com/saguiitay/fdc86365ffb4ee7aa9c7b5e27afc9707
Recommended packages in the Asset Store
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.