ゴマちゃんフロンティア

アザラシが大好きなエンジニアの開発日記です

【Unity】マウスドラッグでオブジェクトからの相対的な線を描画する方法

time 2018/11/10

というわけで、今回は「Unityでマウスドラッグ時に線を描画する」お話です。

この手の話題は「マウスカーソルの位置に線を描画する」といった旨の内容が多いのですが、今回は開発中のゲームの都合で「ドラッグ量に応じて特定のオブジェクトからの相対的な線を引く」ことをしたかったので、その実装方法について考えてみました。

LineRendererの設定

Unityで線を描画するとなれば「LineRenderer」コンポーネントが有名ですね。
Unity4.1の頃のLineRendererはかなりへっぽこだったのですが、最近ではかなり多機能で十分以上に使えるようになってきました。

さっそく空のオブジェクトを作成し、LineRendererコンポーネントを設定します。

デフォルトでPositionsにいくつか入っているので削除しておきましょう。
その他の線の色や太さ、マテリアル等はお好みで。ほとんどデフォルトで大丈夫です。

描画用スクリプトの作成

前述のLineRendererを用いて、マウスドラッグによる線の描画を行うスクリプトを作成します。

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

public class LineRendererController : MonoBehaviour
{
    /// <summary>
    /// マウスドラッグのスピード
    /// </summary>
    [SerializeField]
    protected float dragSpeed = 0.5f;

    /// <summary>
    /// マウスドラッグ中のフラグ
    /// </summary>
    protected bool isDrawing = false;

    /// <summary>
    /// 描画用のラインレンダラー
    /// </summary>
    private LineRenderer currentLineRenderer;

    /// <summary>
    /// 描画する線の位置リスト
    /// </summary>
    private List<Vector3> rendererPositions = new List<Vector3>();

    /// <summary>
    /// 基準とするゲームオブジェクト
    /// </summary>
    [SerializeField]
    protected GameObject originObject;

    /// <summary>
    /// 基準位置から現在ドラッグしている位置までのオフセット
    /// </summary>
    private Vector2 currentOffset = Vector2.zero;

    /// <summary>
    /// 描画を行うマウスのボタン
    /// </summary>
    private const int DRAW_BUTTON = 1;

    void Start()
    {
        currentLineRenderer = gameObject.GetComponent<LineRenderer>();
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(DRAW_BUTTON)) {
            isDrawing = true;
        }
        if (Input.GetMouseButtonUp(DRAW_BUTTON)) {
            // ラインレンダラーの描画地点を初期化
            currentLineRenderer.positionCount = 0;

            // 各種変数を初期化
            rendererPositions.Clear();
            currentOffset = Vector2.zero;

            isDrawing = false;
        }

        // マウス移動時の線を描画
        if (isDrawing) {
            // マウスドラッグに応じたオフセットの取得
            float currentOffset_x = currentOffset.x + Input.GetAxis("Mouse X") * dragSpeed;
            float currentOffset_y = currentOffset.y + Input.GetAxis("Mouse Y") * dragSpeed;
            currentOffset = new Vector2(currentOffset_x, currentOffset_y);

            // 描画先の座標を取得
            Vector3 position = new Vector3(currentOffset_x, currentOffset_y, 0) + originObject.transform.position;

            // ラインレンダラーに座標を設定し線を描画
            if (!rendererPositions.Contains(position)) {
                rendererPositions.Add(position);
                currentLineRenderer.positionCount = rendererPositions.Count;
                currentLineRenderer.SetPosition(currentLineRenderer.positionCount - 1, position);
            }
        }
    }
}

マウスの右クリックしている間のみフラグがtrueになり、描画地点の取得とLineRendererの更新を行います。
Input.GetAxis()の「Mouse X」と「Mouse Y」はデフォルトのInputManagerに定義されています。もし変えてある場合はスクリプト側も合わせて修正してください。
繰り返しになりますが「マウスカーソルの位置」ではないため、マウスドラッグによって基点からどのくらい移動したかを常に記録しておくことがポイントです。このスクリプトではcurrentOffsetフィールドがその役割を担っています。

マウスドラッグ先の描画地点はVector3型のListに追加し、LineRenderer.Positionsの更新時に使用します。描画した地点を取っておかないと、LineRendererの更新時に今まで描画した線が消し飛んでしまいます。

ドラッグ終了時 (=マウス右ボタンを離した時) はLineRenderer.Positionsと描画地点のリストを初期化します。これを忘れると次のドラッグ時に前の地点のものが引き継がれてしまうので気をつけましょう。

動作時の挙動

実際に動かすとこんな感じになります。
マウスカーソルの位置ではなく、ドラッグの方向と量に応じて線が描画されます。

これにiTweenDOTweenなどのトゥイーンライブラリを組み合わせると、引いた線に沿ってオブジェクトを動かしたりすることもできます。今回作った理由はこの仕組みを使いたかったためです。
まだ実用的とは言いがたい部分もあるので、形になってきたらまたご紹介しようと思います。

down

コメントする