UnityでWeb上のベクター画像（SVG）を表示する

[VectorGraphics](https://docs.unity3d.com/Packages/com.unity.vectorgraphics@2.0/api/Unity.VectorGraphics.html)パッケージを使用すると、SVG画像をスプライトとして使用することができます([導入方法](https://qiita.com/ELIXIR/items/4e8170348b7b764c586d))。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/67580772-5bb9-ec4c-7474-fc63f3c49ddb.png)


手元にあるSVGをインポートするだけならこれで十分なのですが、
たとえば https://elix.jp/test/svg/cat.svg にあるSVGを使いたかったので、方法を調べてみました。


まずHierarchy上で

>Create>EmptyObject

で空のオブジェクトを作り、下記のスクリプトをアタッチします

```SVGFromWWW.cs
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;

using UnityEngine;
using UnityEngine.Networking;
using Unity.VectorGraphics;

public class SVGFromWWW : MonoBehaviour
{
    [SerializeField] string m_url = "";
    [SerializeField] SpriteRenderer m_sr = null;
    [SerializeField] MeshRenderer m_mr = null;

    void Start()
    {
        StartCoroutine(WWWCo(m_url));
    }

    // Update is called once per frame
    void Update()
    {
    }

    IEnumerator WWWCo(string _url)
    {
        UnityWebRequest request = UnityWebRequest.Get(_url);
        yield return request.SendWebRequest();

        if (request.downloadHandler.error!="")
        {
            Debug.Log(request.downloadHandler.error);
        }
        else
        {
            Debug.Log(request.downloadHandler.text);
            using (var reader = new StringReader(request.downloadHandler.text))
            {
                SVGParser.SceneInfo sceneInfo =  SVGParser.ImportSVG(reader);

                var geometry = VectorUtils.TessellateScene(sceneInfo.Scene, new VectorUtils.TessellationOptions
                {
                    StepDistance = 1f,
                    SamplingStepSize = 1f,
                    MaxCordDeviation = 0.5f,
                    MaxTanAngleDeviation = 0.1f
                });
                m_sr.sprite = VectorUtils.BuildSprite(geometry, 100, VectorUtils.Alignment.Center, Vector2.zero, 0,true);

                Material mat = new Material(Shader.Find("Unlit/Vector"));
                Texture2D tex = VectorUtils.RenderSpriteToTexture2D(m_sr.sprite, 1024, 1024, mat);
                tex.wrapMode = TextureWrapMode.Clamp;
                m_mr.material.mainTexture = tex;
            }
        }
    }
}
```

次に

>Create>2DObject>Sprites>Square
>Create>3DObject>Quad

でスプライトと平面オブジェクトを作り、m_sr および m_mr にセットします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/52789b47-2852-589c-e781-6ddc8bb4789e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/da011d31-a611-4da8-0f90-96851a65f234.png)

あとは目的のSVGのURLをセットして実行すると、読み込んだSVGがスプライトと平面オブジェクトに表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/afcf1801-0c04-a04a-7322-556f8668d65f.png)

これをさらに[2D Animation](https://qiita.com/ELIXIR/items/150374b29e249d8dca27)させられないかと思ったのですが、さすがに無理でした（Skinning Editorの項目が出ない）。


解説、というほどではないのですが簡単に補足しておくと、SVG画像はXMLベースのテキストなので
```yield return request.SendWebRequest();```
でSVG画像をリクエストして返ってきた```request.downloadHandler.text```を使います。
これをスプライト化するには[VectorUtils](https://docs.unity3d.com/Packages/com.unity.vectorgraphics@2.0/api/Unity.VectorGraphics.VectorUtils.html)というヘルパー関数群のクラスを用います。
まずは

```
                var geometry = VectorUtils.TessellateScene(sceneInfo.Scene, new VectorUtils.TessellationOptions
                {
                    StepDistance = 1f,
                    SamplingStepSize = 1f,
                    MaxCordDeviation = 0.5f,
                    MaxTanAngleDeviation = 0.1f
                });
```
の```StepDistance ``` ```SamplingStepSize ```などのパラメータで画像を構成する要素の細かさ（曲線の粗さ）を決め、要素に分割します。

次に

```
m_sr.sprite = VectorUtils.BuildSprite(geometry, 100, VectorUtils.Alignment.Center, Vector2.zero, 0,true);
```
でそれをスプライト化しています。
Quad(3DObject)に適用するためにはマテリアルにテクスチャを指定する必要があるので、

```
Texture2D tex = VectorUtils.RenderSpriteToTexture2D(m_sr.sprite, 1024, 1024, mat);
```
で作成したスプライトを1024x1024の画像としてテクスチャ化し、マテリアルのテクスチャとして指定しています。