ぷらこあ

雑記/ゲームアイデア帳/成果物ぺろり

5月社内ゲームジャムの成果物「DrawBungeeRope」/ LineRendererで線描画する話

社内ゲームジャムにて

gyazo.com

  • バンジージャンプする人の紐を書いてあげるゲームです。
  • 今回は紐の描画にLineRendererを使ったので使い方を書きます。

LineRenderer

使い方

  • LineRendererは特定の座標間に直線を描画する。

  • 動的に描画しない / 描画してから動かない のであればインスペクタで座標を指定する

    • Positions->size に指定する座標の個数を入力する
    • Positions->ElementX に座標を指定する

gyazo.com

  • 動的に生成したい / 線を動かしたいのであれば、スクリプトで座標を指定する
    • 以下はドラッグ時に線を描画するサンプルコード

      using UnityEngine;
      using System.Collections;
      using System.Collections.Generic;
      using System.Linq;
      
      public class Rope : MonoBehaviour {
      
          public List<Vector2> drawRopePositionList = new List<Vector2>();
          private LineRenderer lineRenderer;
      
          void Start () {
              lineRenderer = GetComponent<LineRenderer>();
      
              // 線の描画を有効にする
              lineRenderer.enabled = true;
          }
      
          void Update () {
              if (Input.GetMouseButton(0)) {
                  Draw();
              }
          }
      
          void Draw () {
              Vector2 mousePosition  = Camera.main.ScreenToWorldPoint(Input.mousePosition);
      
              // drawRopePositionListは後にロープの長さの計算を行うため作成している
              // 線を描画したいだけであれば直接、LineRendererに座標を格納するので良い
              // ただし、余計な描画は避ける為に、最後と同じ位置であれば座標を格納しないようにしている
              if (drawRopePositionList.Count == 0 || (mousePosition != drawRopePositionList.Last())) {
                  drawRopePositionList.Add(mousePosition);
              }
              if (drawRopePositionList.Count > 0) {
                  // 座標の格納可能数を更新する
                  lineRenderer.pSetVertexCount(drawRopePositionList.Count);
                  Vector3 lineRendererPosiotion = new Vector3(mousePosition.x, mousePosition.y, -1.0f);
      
                  // 座標を格納する
                  // SetPosition(index, Vector3)
                  // 既にindexに座標が格納されている場合、更新される
                  // これを利用して毎フレーム毎に伸び縮みする線の描画等も可能
                  lineRenderer.SetPosition(drawRopePositionList.Count - 1, lineRendererPosiotion);
              }
          }
      }
      

描画する線の色や質感を変えたい

  • まず適当なMaterialを作ります
    • Projectビューより create -> Material
  • 作成した Material を LineRenderer -> Materials にて指定する

    • Size を変更することによって複数の質感を同時に適応することも可能
  • (1) Material 自体の色を変更するやり方

    • Material にて “Shader” を “Standard” に変更
    • MainMaps の “Albedo” の項目にて好みの色に変更する
    • 他のパラメータもよしなに変更する
  • (2) LineRendererのParamatersのStartColor/EndColorを変更するやり方

    • Material にて “Shader” を “Particle -> Additive(Soft)” に変更
    • LineRenderer にて Paramaters -> StartColor/EndColor をよしなに変更する
    • このやり方であれば、α値を変更することで線を透過させることも可能

gyazo.com

  • スクリプトからも変更出来るので線をフェードアウトさせることも出来る

    public IEnumerator FadeOut () {
        float a = 1.0f;
        while (a > 0) {
            Vector4 color = new Vector4(1.0f, 1.0f, 1.0f, a);
    
            // SetColors(StartColot, EndColor)
            // 線の先頭と末尾で同じ色を使用しているので同じ値を指定している
            // 先端から徐々にフェードアウトしたい、みたいなケースは個別に指定が必要
            lineRenderer.SetColors(color, color);
            yield return new WaitForSeconds(0.1f);
            a -= 0.1f;
        }
        // α値が0になったら線の描画自体をやめる
        lineRenderer.enabled = false;
        yield break;
    }
    

線がSpriteよりも後ろに描画される

gyazo.com

  • Material に Particle を指定している場合のみ。
  • LineRenderer に限らず Particle は同一の SortingLayer にて Sprite の背面に描画されてしまう。
  • Particle 専用の SortingLayer を用意して、その SortingLayer を前面に出すやり方が簡単。
    • SortingLayer は描画に関するレイヤー
    • Layer は物理挙動に関するレイヤー (異なるレイヤーであれば衝突しない、みたいな設定が出来る)
    • 以下のテラシュールブログさんの記事がすごいためになる。

tsubakit1.hateblo.jp

Unityのスプライトの描画順は「SortingLayer、Order In Layer、Z値」の順番で設定します。

  • レイヤーの追加

    • 上部メニューより Edit -> ProjectSettings -> Tags and Layers を開く
    • SortingLayersに適当な名前のレイヤーを追加する
  • レイヤーの指定(インスペクタ)

    • SpriteRenderer に SortingLayer を指定する箇所があるのでそこで指定する
  • レイヤーの指定(スクリプト)

    • LineRenderer のように SortingLayer の指定箇所が無い場合はスクリプトにて指定する

      private LineRenderer lineRenderer;
      void Start () {
          lineRenderer = GetComponent<LineRenderer>();
          lineRenderer.enabled = true;
          lineRenderer.sortingLayerName = "Particle";
      }