[unity]Line Renderer で☆を描画する

Unity で自由に線を引くには Line Renderer というコンポーネントがお手軽です。
今回はこれを使って☆を描画してみようと思います。

オブジェクトを配置

まず、空の GameObject を作成し、Line Renderer コンポーネントを追加します。
3D/Sphere は描画の先端を表す球体です。

Line Renderer のインスペクタを設定

オレンジの箇所を設定します。

Color

虹色にしたかったので、頑張って調整。
キーは合計8つまでなんですね…お陰で数値が割り切れなかった。

Corner Vertices, End Cap Vertices

角や終端を多角形にすることで、丸みを出すことができます。

0
10。端っこが丸くなりました

Materials

設定必須。Default-Line を選択しましょう。

設定しないと unity ではお馴染みピンク表示になってしまいます。

Width

こちらは任意で。始点から終点の線の太さを設定します。
初期状態のままだと、結構太目のラインです。

☆を描画するスクリプト

以下のスクリプトを Line Renderer と同じオブジェクトに貼り付けます。

using System.Collections;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{
    [SerializeField]
    LineRenderer    render;
    [SerializeField]
    GameObject      sphere;

    IEnumerator Start()
    {
        yield return null;

        Vector3[] point = new Vector3[6];

        point[0] = Quaternion.Euler(0, 216.0f, 0) * new Vector3(0, 0, 10);
        point[1] = Quaternion.Euler(0,   0.0f, 0) * new Vector3(0, 0, 10);
        point[2] = Quaternion.Euler(0, 144.0f, 0) * new Vector3(0, 0, 10);
        point[3] = Quaternion.Euler(0, 288.0f, 0) * new Vector3(0, 0, 10);
        point[4] = Quaternion.Euler(0,  72.0f, 0) * new Vector3(0, 0, 10);
        point[5] = Quaternion.Euler(0, 216.0f, 0) * new Vector3(0, 0, 10);

        for (int no = 0; no < 6; no++)
        {
            render.positionCount = no+1;
            render.SetPositions(point);
            if (no > 0)
            {
                float time = 0;

                while (time < 0.9f)
                {
                    time += Time.deltaTime * 2;
                    if (time > 0.9f)
                    {
                        time = 0.9f;
                    }

                    Vector3 p = point[no-1] + ((point[no] - point[no-1]) * (time + 0.1f));
                    render.SetPosition(no, p);
                    sphere.transform.position = p;
                    yield return null;
                }
            }

            yield return null;
        }
    }
}

忘れずインスペクタに、オブジェクトをアタッチしてください。
(これをやっておかないとエラーで実行されません)

以下、ソースコードについて軽く説明します。

☆の書き方

☆の頂点は5角形の頂点と同じです。
5角形は同じ円の上に存在します。5等分するので、1つにつき 72 度間隔をあけます。

書き順は左下①~⑤の順番になるので、その頂点順に頂点座標を求めています。
point[0] と point[5] が同一なのは、☆を書く時の始点と終点が同じ場所だからです。

point[0] = Quaternion.Euler(0, 216.0f, 0) * new Vector3(0, 0, 10);
point[1] = Quaternion.Euler(0,   0.0f, 0) * new Vector3(0, 0, 10);
point[2] = Quaternion.Euler(0, 144.0f, 0) * new Vector3(0, 0, 10);
point[3] = Quaternion.Euler(0, 288.0f, 0) * new Vector3(0, 0, 10);
point[4] = Quaternion.Euler(0,  72.0f, 0) * new Vector3(0, 0, 10);
point[5] = Quaternion.Euler(0, 216.0f, 0) * new Vector3(0, 0, 10);

線を伸ばしながら描画する

26-45 行目は線を伸ばしながら描画している部分です。

time += Time.deltaTime * 2;

0.45 秒で線を1つ描画しています。
Time.deltaTime は yield return してからの経過時間です。

Vector3 p = point[no-1] + ((point[no] - point[no-1]) * (time + 0.1f));

始点+ (終点ー始点) × 時間(0~1) の計算式で、経過時間ごとの「始点から終点までのポジション」を計算します。
このあたり直感的にわからない場合は、Debug.Log などで具体的に数字を表示するといいかもしれません。

ワンポイント

time が 0.0~0.9 を範囲として、後から 0.1 足しているのは Line Renderer の特性で表示がおかしくなってしまう部分を誤魔化しています(笑)

time を 0.0~1.0 とするコードはこちらです(差し替え分)。

while (time < 1.0f)
{
    time += Time.deltaTime;
    if (time > 1.0f)
    {
        time = 1.0f;
    }

    Vector3 p = point[no-1] + ((point[no] - point[no-1]) * time);
    render.SetPosition(no, p);
    sphere.transform.position = p;
    yield return null;
}
途中、線が細くなっている

time を 0.0~1.0 として素直に動かした場合、頂点付近を描画する際「線が細く」なっているのがわかるでしょうか。
これは一瞬ですが不安定な動作と言えます。

はっきりと理由を解析していません(頂点を綺麗に描画するためのロジック上、2頂点の位置が近すぎると計算誤差がひどくなるため、とか?)が、その特性も加味しつつ、正しく動かすために time を 0.1~1.0 として不安定な部分をクリアしました。

時間が許すのであれば、不安定になってしまう理由をひたすら追求するのもいいですね!
初心者にはオススメしませんが…。

返信を残す

メールアドレスが公開されることはありません。

CAPTCHA