おもちゃラボ

Unityで遊びを作ってます

【AR Foundation】マーカーを使ったARを作る

この記事では、AR Foundationでマーカーを使ったARを作る方法を紹介します。マーカー型のARといえばVuforiaが有名でしたが、ARKit3からはARKit/ARCoreでも精度よくロバストな検出ができるようになっています。

f:id:nn_hokuson:20201109131911j:plain:w650

AR Foundationの基礎になっているARKitについては「swiftで作る ARKit超入門」がオススメです!こちらも、ぜひご参照ください。
booth.pm

今回の目次は次のとおりです。

プロジェクトの作成と準備

AR Foundationを使ったプロジェクトの作り方と、その準備についてはこちらの記事に詳しく説明しています。

nn-hokuson.hatenablog.com

ここでは、ヒエラルキーウインドウにAR SessionとAR Session Originオブジェクトを配置し終えたところからスタートします。

f:id:nn_hokuson:20201108093632j:plain

AR Foundationでマーカーを使ったARを作る流れは次のとおりです。

  1. ARマーカー用のライブラリを作成
  2. 作成したライブラリにARマーカーを登録
  3. 登録したARマーカーに紐付けるモデルを指定

それではこの流れに沿って、ARを表示する手順を見ていきましょう。

ARマーカーのライブラリを作成する

AR Foundationでマーカーを使ったARを作る場合、まずはARマーカーにしたい画像をライブラリに登録します。

まずはARマーカーのライブラリを作成します。ライブラリを作成するにはプロジェクトウィンドウで右クリック→Create→XR→Reference Image Libraryを選択してください。

f:id:nn_hokuson:20201108093641p:plain:w500

次に、作成したImage LibraryにARマーカーを登録します。作成したReference Image Libraryを選択して、インスペクタからAdd Imageのボタンをクリックします。

f:id:nn_hokuson:20201108093655j:plain

新しくARマーカーを登録する画面が表示されるので、ARマーカーをドラッグ&ドロップします。

次に「Specify Size」 にチェックを入れ、ARマーカーの実物サイズを指定します。入力はメートル単位なので、例えば5cm x 5cmのマーカーであれば0.05と入力してください。このARマーカーの物理サイズを指定しないと実行時にエラーになるので注意です!

f:id:nn_hokuson:20201108093714j:plain

AR Tracked Image Managerの設定

ARマーカーライブラリの作成ができたので、次はこのライブラリをTracked Image Managerに登録します。Tracked Image Managerでは

  • ARマーカーライブラリの登録
  • ARマーカーの個数の上限
  • ARマーカーが検出されたときに表示するARモデルの登録

の設定を行います。

まずはヒエラルキーウインドウでAR Session Originを選択して、インスペクタのAdd Componentから「AR Tracked Image Manager」をアタッチします。

f:id:nn_hokuson:20201108093843j:plain

次にSerialized Libraryの欄に、作成したReferenceImageLibraryをドラッグ&ドロップします。また、Max Number of Moving Imagesにトラッキングするマーカーの個数、Tracked Image PrefabにARマーカーが検出されたときに表示するARモデルを設定します。

f:id:nn_hokuson:20201108093748j:plain

これでAR Tracked Image Managerの設定は終わりです。最後にAR Foundationの各種設定を次の記事を参考にして行い、実行してみてください。

nn-hokuson.hatenablog.com

ARマーカーの上に指定したARモデルが表示されれば成功です!

f:id:nn_hokuson:20201109133455g:plain:w450

まとめ

この記事では、AR Foundationを使ってマーカー型のARを表示する方法を紹介しました。AR Foundationではマーカーを使ったARの他にも色々と面白い機能がありますので、こちらも今後、紹介していきたいと思います。

テクスチャの黒色部分を透明化する

Unityではテクスチャの設定で「Alpha Source:From Gray Scale」というものがあります。これは画像のグレースケール値をアルファチャネルに設定するものです。

f:id:nn_hokuson:20201031115503p:plain:w400

これをPhotoshopでやろうとすると、マスクを作ったり、アルファチャネルを追加したりと案外大変だったのでpythonでスクリプトを作りました。

import cv2

#読み込み
img = cv2.imread('src.jpg')

#グレースケール化
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

#アルファチャネルに追加
r, g, b = cv2.split(img)
img = cv2.merge((r, g, b, gray))

#保存
cv2.imwrite('dst.png', img)

やっていることとしては、まずOpenCVでRGB画像を読み込み、これをグレースケール化したものをアルファチャネルに追加してマージしているだけです。

f:id:nn_hokuson:20201031121929p:plain:w500

【Unity】ファイルの読み込みと書き込み方法3選

f:id:nn_hokuson:20201027151808p:plain:w650

Unityを使っていると、ファイルから読み込んだり、ファイルに書き込みをしたい場合が良くあります。C#にはファイルの読み書きをする方法がいくつか用意されていて微妙にややこしいので簡単にまとめておこうと思います。

TextAssetを使って読み込む

テキストファイルを読み込みたいときに一番簡単な方法です。スクリプト中でTextAsset変数を宣言しておき、インスペクタから読み込みたいテキストをセットします。

using UnityEngine;

public class Test : MonoBehaviour
{
    public TextAsset data;

    void Start()
    {
        Debug.Log(data.text);
    }
}

Fileクラスを使って読み書きする

Fileクラスを使うと、ファイルのオープンやクローズといった面倒なステップを踏まずにファイルの読み書きができます。一方で、シークや一部読み込みなどの細かい制御はできないので、その場合は次のStreamを使う必要があります。

using UnityEngine;
using System.IO;

public class Test : MonoBehaviour
{
    void Start()
    {
        // 書き込み
        string path = Application.persistentDataPath + "/test.txt";
        File.WriteAllText(path, "hoge");

        // 追記
        File.AppendAllText(path, "fuga");
        Debug.Log("Save at " + path);

        // 読み込み
        string data = File.ReadAllText(path);
        Debug.Log("Data is " + data);
    }
}

Fileクラスには、テキストデータの読み書きのためのWriteAllText, ReadAllTextの他に、バイナリデータを読み書きできるReadAllBytesとWriteAllBytesも用意されています。これらを使えば次のようにテクスチャの画像を保存することもできます。

using UnityEngine;
using System.IO;

public class Test : MonoBehaviour
{
    public Texture2D texture;

    void Start()
    {
        // テクスチャをバイト列にする
        byte[] data = texture.EncodeToPNG();

        // 画像の保存
        string path = Application.persistentDataPath + "/test.png";
        File.WriteAllBytes(path, data);
    }
}

Streamを使う

Unityで柔軟にファイルの読み書きをしたい場合はStreamReaderやStreamWriterを使います。StreamReaderには一行ずつ読み込むReadLineメソッドやファイル末尾まで一気に読み込むReadToEndメソッドが用意されています。また、StreamWriterの第2引数によって上書き保存か追記かを選択できます。

using UnityEngine;
using System.IO;

public class Test : MonoBehaviour
{
    void Start()
    {
        // 書き込み
        string path = Application.persistentDataPath + "/test.txt";
        bool isAppend = true; // 上書き or 追記
        using (var fs = new StreamWriter(path, isAppend, System.Text.Encoding.GetEncoding("UTF-8")))
        {
            fs.Write("ホップ\nステップ\nジャンプ");
        }

        // 一気に読み込む
        using (var fs = new StreamReader(path, System.Text.Encoding.GetEncoding("UTF-8")))
        {
            string result = fs.ReadToEnd();
            Debug.Log(result);
        }

        // 一行ずつ読み込む
        using (var fs = new StreamReader(path, System.Text.Encoding.GetEncoding("UTF-8")))
        {
            while (fs.Peek() != -1)
            {
                Debug.Log(fs.ReadLine());
            }

        }
    }
}

usingステートメントを使うことでファイルのクローズ忘れなどを防ぐことができます。usingステートメントについては「確かな力が身につくC#超入門 第2版」でも少し触れているので、あわせてご覧ください。