As of today, I don’t think there’s a way around it. You could probably automate the process with asset post-processors, however.
Hey,
I am currently writing a custom SVG tool based on the SVG importer. Since you parse the SVG file and build SceneNode objects, would it be possible to add the node’s ID and parent property directy into the object? That would make node hierarchy traversal so much easier, without the need to use the SceneInfo object.
For now I have written a class that derives from SceneNode and replace each node with the extended version.
public class SceneNodeEx : SceneNode
{
public string ID{ get; private set; }
public int HierarchyLevel{ get; private set; }
public SceneNodeEx Parent{ get; private set; }
public SceneNodeEx( SceneNode node )
{
Children = node.Children;
Shapes = node.Shapes;
Transform = node.Transform;
Clipper = node.Clipper;
if( node is SceneNodeEx ex )
{
ID = ex.ID;
HierarchyLevel = ex.HierarchyLevel;
Parent = ex.Parent;
}
}
public SceneNodeEx( SceneNode node, string id, int hierarchyLevel, SceneNodeEx parent )
{
Children = node.Children;
Shapes = node.Shapes;
Transform = node.Transform;
Clipper = node.Clipper;
ID = id;
HierarchyLevel = hierarchyLevel;
Parent = parent;
}
}
All your utilities are internal so it was easier to just fork the library. It did work, however.
This just a temporary solution since the SVGs are not anti-aliased (AFAICT), so we’ll need to a raster format before launch.
EDIT: Found my answer over here Unity UI SVG support script . Since it was a gradient svg I needed to enable TextCoord2 in the “Additional Shader Channel” for the Canvas.
I have an SVG with Generated Asset Type = “UI SVGImage”.
I’d like to use this in my UI on a Screen Space - Camera canvas.
The preview looks fine below but when I try to drag it into the canvas, or assign it to a SVG Image component I get a blank white square. What am I doing wrong here?
Here is the import and correct-looking preview:
Here is the SVG Image component in the scene that produces the plain white square:
I have a similar issue as @huwp . The following function is basically taken right from the website example (Rendering vector graphics). I get the error Not allowed to override geometry on sprite ‘’ logged to the console from BuildSprite and the returned texture is simply empty.
public static Texture2D RenderSVG(string svgDocument, int textureSize, int pixelsPerUnit = 1)
{
// load
var svg = SVGParser.ImportSVG(new StringReader(svgDocument));
// render to texture
var geom = VectorUtils.TessellateScene(svg.Scene, new()
{
StepDistance = 100.0f,
SamplingStepSize = 0.01f,
MaxCordDeviation = 0.5f,
MaxTanAngleDeviation = 0.1f
});
var sprite = VectorUtils.BuildSprite(geom, pixelsPerUnit, VectorUtils.Alignment.TopLeft, Vector2.zero, 128, true);
return VectorUtils.RenderSpriteToTexture2D(sprite, textureSize, textureSize, GetSVGRenderMaterial(), 1, true);
}
In some situations it works fine. Apparently, it works only if called from certain situtations such as from a Start method (see this post )? However, I also absolutely need to do this in a chain of Awake calls. What is this limitation, why is it not documented and how can I work around it?
Even though the wrong shader name is fixed, this is still necessary for the function to work in a build. This is also not documented, it should also probably happen automatically when the package is installed?
@mcoted3d I think SVGImage should have useLegacyMeshGeneration field set to false on the constructor, because it’s set to true by default in Graphic (other UI components like Image, RawImage, Text etc set it to false). This means that it’s taking a path where it builds the geometry to a mesh directly and passes that to the IMeshModifiers, but this is deprecated… Instead it should use the newer method which uses VertexHelper. This no zero downsize and would allow my Unity UI effects and filters to run on SVGImage with better performance and without calling the deprecrated method.
Thanks,
These limitations only occurs in the Editor, where you can only override the geometry during the import phase (e.g., using an asset preprocessor). At runtime, you should always be allowed to override the mesh.
Seems like a bug on Unity’s side. It would be worth upgrading to the latest Unity patch version to see if this is fixed. Otherwise, please file a bug report:
https://discussions.unity.com/t/842010
Does this package support 9-Slicing in a uGUI context?
For more detail, I’m working with a good number of SVGs that contain rasterized images (as unfortunate as that situation is) and I’m curious if they will support 9-Slicing via the Sprite Editor. All of my SVGs are imported with GeneratedAsssetType being UI SVGImage
. I added one to the scene under a Canvas and it didn’t do any 9-Slicing in either the editor scene preview or the game view in play mode.
Does it work with UI Toolkit only?
If it is not supported under uGUI and UI SVGImage
, what package script files should I look into modifying to add this functionality to a fork I have? (Any guidance on making these changes myself would be appreciated)
Unity Version: 2021.3.f1 (Not opposed to updating to 2022/3 LTS)
Package Version: 2.0.0-preview.24
Also, while I’m thinking about it, the package doesn’t fully support the MIME type spec, as in 2.0.0-preview.24 the SVGParser would skip over images with the MIME type image/PNG
, which while rare to see in the wild, isn’t invalid. To fix this in my fork I changed line 1944 of Runtime/SVGParser.cs to add a .ToLower()
call on dataURI.Substring(...)
. This works for me because I control what SVGs my fork loads so I don’t know if this is the fully robust solution, but I thought this was worth sharing.
The challenge with 9-sliced SVGs is that it requires taking the original SVG mesh, which has an arbitrary number of triangles, and splitting it into 9 sections for the slices. This clipping process is non-trivial and expensive, which is the main reason why we didn’t provide it for UGUI. We had more optimization avenues for UI Toolkit, but it’s still a complex process.
I think you would have to look into the SVGImage’s OnPopulateMesh() to make it work.
Would be worth filing a bug for this (Help > Report a Bug…), this is something we should fix.
This makes sense. For my use case, I’m able to guarantee what the geometry will be as anything I need to 9-Slice will only have one quad in the SVG, so it may be easier for me to make changes specific to that. However, I am also able to just import the image directly for now instead of using the SVG, as the SVG only serves to provide positional information, so I will be 9-Slicing that as its already supported (though if time permits I may look into making the changes).
Bug report has been filed. I appreciate the follow up!
is there a function to export an SVG from this package?
No, this is purely an SVG importer.
You could write a vector Scene → SVG text file on your own though. Depending on your specific SVG feature requirements, I don’t expect it to be a ton of work.
I started working with vector graphics sample package and I found this. Is this new bug
? When you change from skybox to solid color background color it disappeared.
Created a simple spline using vector graphics package. Here is code.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.VectorGraphics;
public class EditShape : MonoBehaviour
{
[SerializeField] Transform[] positionPoint;
[SerializeField] Transform[] positioinHandleP1;
[SerializeField] Transform[] positioinHandleP2;
[SerializeField] int numberOfSegments;
BezierPathSegment[] bezierPathSegment;
[SerializeField] SpriteRenderer spriteRenderer;
[SerializeField] List<VectorUtils.Geometry> geometryTessellated;
[SerializeField] VectorUtils.Alignment alignment;
[SerializeField] float pixelsPerUnit;
[SerializeField] float stepDistance = 100f;
VectorUtils.TessellationOptions tessellationOptions;
Scene scene;
void Start()
{
scene = new Scene()
{
Root = new SceneNode()
{
Shapes = new List<Shape>()
}
};
UpdateShape();
}
void Update()
{
UpdateShape();
}
void UpdateShape()
{
bezierPathSegment = new BezierPathSegment[3]
{
NewBezierSegments(0),NewBezierSegments(1), new BezierPathSegment{
P0 = positionPoint[positionPoint.Length - 1].position
}
};
Shape shape = new Shape()
{
Contours = new BezierContour[]
{
new BezierContour
{
Closed = false, Segments = bezierPathSegment
}
},
PathProps = new PathProperties
{
Stroke = new Stroke() { Color = Color.white, HalfThickness = 0.1f }
}
};
tessellationOptions = new VectorUtils.TessellationOptions()
{
StepDistance = stepDistance,
MaxCordDeviation = 0.1f,
MaxTanAngleDeviation = 0.1f,
SamplingStepSize = 0.01f
};
scene.Root.Shapes.Clear();
scene.Root.Shapes.Add(shape);
geometryTessellated = VectorUtils.TessellateScene(scene, tessellationOptions);
Sprite sprite = VectorUtils.BuildSprite(geometryTessellated, pixelsPerUnit, alignment, Vector2.zero, 128, false);
spriteRenderer.sprite = sprite;
}
BezierPathSegment NewBezierSegments(int index)
{
return new BezierPathSegment
{
P0 = positionPoint[index].position,
P1 = positioinHandleP1[index].position,
P2 = positioinHandleP2[index].position
};
}
}
Which render pipeline are you using? It looks like a bad interaction between that render pipeline and the sprites.
Universal render pipeline 2021 lts but i tried it on Universal 2022 lts as well but had the same problem. Maybe you forgot scene.Root.Shapes.Clear() function. Maybe it’s adding multiple shapes and not clearing it
Thanks for pointing this out, I think you are correct.