【Unity】ScrollView 上で線(Line)を描画する

本記事では、UnityでScrollView上で線を描画する方法について書きます。

ScrollView上で、線を描画するために、

  • ScrollViewのContentにImageコンポーネントをアタッチしたゲームオブジェクトを設定する
  • Imageにドットの集合で線を描画する

ということをしました。

他にもっと簡単にできる方法があるかもしれません。が、見つけられなかったので、この方法を採用しました。

MackableGraphic クラスを使用しても線は描画できます。しかし、ScrollView上で線を描画する場合、スクロールすると、線がはみ出ます。これはGUIで使うものではないように思います。

開発環境
  • Windows10 Home 64bit
  • Unity Version 2020.3.17f1 Personal
  • Visual Studio Community 2019  16.11.2
  • .NET Standard2.0
目次

やりたいこと

  • ScrollView 上に星型のラインを表示する
  • ScrollView のバーを動かしたとき、ラインがスクロールビューからはみ出ないようにする
  • ラインの表示非表示を自由にできるようにする

実際に実装したものは↓のような動きをします。

ライン表示を実装する

SampleSence上に、ScrollView を作成しました。

ScrollView → Viewport → Content の子ゲームオブジェクトに、

  • 背景白のImageコンポーネントを実装したゲームオブジェクト
  • 背景透明、黒色の星ラインのImageコンポーネントを実装したゲームオブジェクト

をScriptで追加します。2つを重ねて表示することでラインを表示します。

黒色の星ラインのゲームオブジェクトを非アクティブ化することで、ラインを消すことができます

動画はGUIで表示切替をしてますが、スクリプトでもSetActiveを使えばできます。

ScrollView にアタッチするMonoBehaiver の拡張クラスは↓のようになります。

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

namespace Assets.Script
{
    /// <summary>
    /// ScrollView -> Viewport -> Content
    /// </summary>
    class StarImage : MonoBehaviour
    {
        /// <summary>星ライン座標一覧</summary>
        private readonly LineCords StarLineCords = new LineCords(
            new List<LineCord>()
            {
                new LineCord(200,143),
                new LineCord(288,79),
                new LineCord(254,183),
                new LineCord(342,246),
                new LineCord(233,246),
                new LineCord(200,350),
                new LineCord(167,246),
                new LineCord(58,246),
                new LineCord(146,183),
                new LineCord(112,79)
            });

        /// <summary>星ライン幅</summary>
        private readonly int StarLineWidth = 5;

        /// <summary>イメージ幅</summary>
        private readonly int ImageWidth = 400;

        /// <summary>イメージ高さ</summary>
        private readonly int ImageHeight = 400;

        private void Start()
        {
            GameObject viewport = transform.Find("Viewport").gameObject;

            GameObject content = viewport.transform.Find("Content").gameObject;
            content.GetComponent<RectTransform>().sizeDelta = new Vector2(ImageWidth, ImageHeight);

            // 背景イメージ ゲームオブジェクトの生成
            GameObject backGameObject = Instantiate(new GameObject());
            backGameObject.AddComponent<Image>();
            backGameObject.transform.parent = content.transform;
            backGameObject.name = "BackImage";
            backGameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(ImageWidth, ImageHeight);
            backGameObject.GetComponent<RectTransform>().anchorMin = new Vector2(0, 1);
            backGameObject.GetComponent<RectTransform>().anchorMax = new Vector2(0, 1);
            backGameObject.GetComponent<RectTransform>().pivot = new Vector2(0, 1);
            backGameObject.transform.localPosition = new Vector3(0, 0, 0);

            // 背景を白にする
            Color backColor = new Color(255, 255, 255, 255);
            Texture2D backTexture = new Texture2D(ImageWidth, ImageHeight, TextureFormat.ARGB32, false);
            for (int x = 0; x < ImageWidth; x++)
            {
                for (int y = 0; y < ImageHeight; y++)
                {
                    backTexture.SetPixel(x, y, backColor);
                }
            }

            // 背景の反映
            Image backImage = backGameObject.GetComponent<Image>();
            backImage.sprite = Sprite.Create(backTexture, new Rect(0, 0, backTexture.width, backTexture.height), new Vector2(0.5F, 0.5F));
            backTexture.Apply();
            
            // ラインイメージ ゲームオブジェクトの生成
            GameObject lineGameObject = Instantiate(new GameObject());
            lineGameObject.AddComponent<Image>();
            lineGameObject.transform.parent = content.transform;
            lineGameObject.name = "LineImage";
            lineGameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(ImageWidth, ImageHeight);
            lineGameObject.GetComponent<RectTransform>().anchorMin = new Vector2(0, 1);
            lineGameObject.GetComponent<RectTransform>().anchorMax = new Vector2(0, 1);
            lineGameObject.GetComponent<RectTransform>().pivot = new Vector2(0, 1);
            lineGameObject.transform.localPosition = new Vector3(0, 0, 0);

            Texture2D lineTexture = new Texture2D(ImageWidth, ImageHeight, TextureFormat.ARGB32, false);

            // 背景を白にする
            Color lineBackColor = new Color(255, 255, 255, 0);
            for (int x = 0; x < ImageWidth; x++)
            {
                for (int y = 0; y < ImageHeight; y++)
                {
                    lineTexture.SetPixel(x, y, lineBackColor);
                }
            }
            // ラインを黒にする
            Color lineColor = new Color(0, 0, 0, 100);

            // ラインのドットに黒を設定する
            List<Tuple<int, int>> list = StarLineCords.CreateLineDotListCircle(StarLineWidth);
            foreach (Tuple<int, int> dot in list)
            {
                lineTexture.SetPixel(dot.Item1, dot.Item2, lineColor);
            }

            // ラインの反映
            Image lineImage = lineGameObject.GetComponent<Image>();
            lineImage.sprite = Sprite.Create(lineTexture, new Rect(0, 0, lineTexture.width, lineTexture.height), new Vector2(0.5F, 0.5F));
            lineTexture.Apply();
        }
    }
}

ラインのドット一覧を出力する、ライン座標クラス LineCords はここでは割愛します。プロジェクトは↓からダウンロードできます。

GitHub
GitHub - HomeProgrammer81/ScrollViewLine at master_lineStar Contribute to HomeProgrammer81/ScrollViewLine development by creating an account on GitHub.

まとめ

UnityでScrollView上で線を描画する方法について書きました。

ScrollView上で、線を描画するために、

  • ScrollViewのContentにImageコンポーネントをアタッチしたゲームオブジェクトを設定する
  • Imageにドットの集合で線を描画する

をしました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次