たるこすの日記

たるこすの日記

リアルからバーチャルへ、バーチャルからリアルへ

Unity で2Dお絵かきアプリを作る

こんにちは、たるこすです。
今回は Unity を使って2Dお絵かきアプリを作ります。

お絵かきアプリを作ることが最終目的ではないのですが、 それについては別の投稿記事で話したいと思います。

まずは実装してみる

まずは、こちらのサイトを参考に実装してみます。
Unityでテクスチャにお絵描きしよう - おもちゃラボ

  • 2D アプリケーションとしてUnityプロジェクトを作成
  • Plane を作成して画面に映るサイズに調整
  • 黒色の画像をインポートし、以下のように設定 f:id:tarukosu:20170212202857p:plain
  • マテリアルを作成し、上のテクスチャを設定 f:id:tarukosu:20170212202856p:plain
  • 以下のスクリプトを作成し、Plane に追加
using UnityEngine;
using System.Collections;
using System.IO;

public class PaintManager : MonoBehaviour
{
    Texture2D drawTexture;
    Color[] buffer;
    bool touching = false;
    Vector2 prevPoint;

    public NetworkManager networkManager;

    void Start()
    {
        Texture2D mainTexture = (Texture2D)GetComponent<Renderer>().material.mainTexture;
        Color[] pixels = mainTexture.GetPixels();

        buffer = new Color[pixels.Length];
        pixels.CopyTo(buffer, 0);

        drawTexture = new Texture2D(mainTexture.width, mainTexture.height, TextureFormat.RGBA32, false);
        drawTexture.filterMode = FilterMode.Point;
    }

    public void DrawLine(Vector2 p, Vector2 q)
    {
        var lerpNum = 10;
        for(int i=0; i < lerpNum + 1; i++)
        {
            var r = Vector2.Lerp(p, q, i * (1.0f / lerpNum));
            Draw(r);
        }
    }

    public void Draw(Vector2 p)
    {
        p.x = (int)p.x;
        p.y = (int)p.y;

        var brushSize = 10;
        var color = Color.white;
        for (int x = Mathf.Max(0, (int)(p.x - brushSize-1)); x < Mathf.Min(drawTexture.width, (int)(p.x + brushSize+1)); x++)
        {
            for (int y = Mathf.Max(0, (int)(p.y - brushSize-1)); y < Mathf.Min(drawTexture.height, (int)(p.y + brushSize+1)); y++)
            {
                if (Mathf.Pow(p.x - x,2) + Mathf.Pow(p.y -y, 2) < Mathf.Pow(brushSize, 2))
                {
                    buffer.SetValue(color, x + drawTexture.width * y);
                }
            }
        }
    }

    void Update()
    {
        if (Input.GetMouseButton(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, 100.0f))
            {
                var drawPoint = new Vector2(hit.textureCoord.x * drawTexture.width, hit.textureCoord.y * drawTexture.height);
                if (touching) {
                    DrawLine(prevPoint, drawPoint);
                }
                else
                {
                    Draw(drawPoint);
                }
                prevPoint = drawPoint;
                touching = true;
            }else
            {
                touching = false;
            }
            drawTexture.SetPixels(buffer);
            drawTexture.Apply();
            GetComponent<Renderer>().material.mainTexture = drawTexture;
        }else
        {
            touching = false;
        }
    }
}

これで、マウスのドラッグで線がかけるようになりました。
ただ、この方法だとブラシの形を変えることができません。

そこで、自作は一旦諦め、アセットが使えないか試してみます。

UnityTexturePaint を使ってみる

Unity Texture Paint というアセットを使わせていただきます。
ソースコード や UnityPackage は以下のリポジトリにあります。
GitHub - EsProgram/UnityTexturePaint: Texture-Paint on Unity.

ダウンロード後、UnityTexturePaint.unitypackage を自分のプロジェクトにインポートします。

Asset Store でも販売されているので、購入してインポートすることもできます。
Asset Store

スクリプトの設定

Main Camera に Mouse Painter スクリプトを追加します。

Brush Texture には、単純な円を書いたテクスチャを作成しそれをセットしました。
また、以下のように一部パラメータを変更しました。

  • Brush Scale : 0.02
  • Brush Color : #FFFFFFFF

次に、Plane を作成し、カメラに映るよう位置を調整します。
Plane には Dynamic Canvas スクリプトを追加します。
設定はそのままでOKです。

また、Material を作成し、Shader を Unlit/Texture に、テクスチャを透明な画像に変更します。
この Material を Plane に設定します。

これだけで、マウス操作でお絵かきができるようになりました。
とっても簡単です。
最初からこっちを使っておけばよかった


Unity で 2Dお絵かきアプリを作成

終わりに

今回作成したお絵かきアプリは Android アプリとして利用します。
Android の場合はマウス操作ではなくタップ操作になりますが、コードを変更する必要はありませんでした。

続き: Unity お絵かきアプリで魔法陣を書く - たるこすの日記