VIVITABLOG

VIVITAで活躍するメンバーの情報発信サイト

Unityアプリを別端末のスマホアプリと連携させる

こんにちは。板本@itamotoです。

最近はVIVISTOPでも、ゲームを作りたいとScratchやUnityを使って開発を始める子供を見かけるようになってきました。
比較的初心者でも、わりとすぐに動くものができるので子供とでも一緒に楽しめるツールです。

弊社やまもりも以前に紹介してますね。 blog.vivita.io

今回はそのUnityAndroidアプリを連携させた例を紹介させてもらおうと思います。 (iPhoneアプリであってもUnity側は変えずに連携可能です)

連携して何をしたいのか

これをやる目的としては、これまでロボコン等でも紹介させてもらったVIVIPARTS(*1)とVIVIPROGRAMMER(*2) を使ったものづくりをする上で画面の中のリッチビジュアル表現とインタラクティブなものが作りたかったというのがあります。

Unityのゲームを子どもたちが自分で作ったコントローラーで遊んだり、
UnityでVRアプリを作って、ヴァーチャルの世界の風や水しぶきをリアルで演出するものを自作することもできそうです。
色々とものづくりの表現の幅は広がると思います。

f:id:itamoto:20181108173318p:plain
実際にVIVIPARTSのコントローラーでUnityゲームを遊んでいます


(*1)弊社開発中のアクチュエーターやセンサー機能をもったハードウエア
(*2)VIVIPARTSを動かすためのビジュアルプログラミングアプリ

連携するプロトコルにはOSCを利用しました。

OSC (Open Sound Control) を利用しました。
OSCはアプリケーション間の通信プロトコルで、主にUDPで使われています。
UDPで利用する以上、受信されたかどうかは保証されないのでその点ではOSCを使えるケースなのか判断が必要とされると思います。
今回のアプリ連携も、UnityアプリとAndroidアプリの実行端末は同じネットワーク内で動いていることを前提としています。

Unity側の実装について

  • Unityのプロジェクトを作成します。(2D、3Dは問いません)既存のプロジェクトを利用しても問題ないです。
  • OSCのサーバー、クライアント機能を呼べるUnityOSCをダウンロードしてきます。(UnityOSCダウンロード)
  • ダウンロードしたzipファイルを解凍し、その中の/src/OSC ディレクトリと/src/OSCHandler.cs2つをUnityプロジェクト内のAssetsフォルダ直下にコピーします。
  • OSCHandler.cs内のInitメソッドを編集します。
   public void Init()
    {
        //Initialize OSC clients (transmitters)
        //Example:     
        CreateClient("SuperCollider", IPAddress.Parse("127.0.0.1"), 5555);

        //Initialize OSC servers (listeners)
        //Example:

        CreateServer("AndroidPhone", 6666);
    }

UnityアプリからAndroidアプリへのデータ送信を行う場合はCreateClientを有効に
AndroidアプリからUnityへのデータ送信を行う場合はCreateServerを有効に
相互にデータ通信したい場合には両方を有効にしてください。
(最初は全てコメントアウトされています)

CreateClientの引数は、
1. サーバーID(送信時に必要)
2. サーバーのIPアドレス
3. 利用するポート

CreateServerの引数は
1. サーバーID(任意の文字列で大丈夫でした)
2. 利用するポート
となっています。適宜編集してください。

  • 最後にスクリプトを新規作成し、任意のGameObjectのComponentに追加します。 ここではOscScript.csを作成するものとしました。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityOSC;
public class OscScript : MonoBehaviour
{
    private long lastTimeStamp;

    void Start()
    {
        OSCHandler.Instance.Init();
        lastTimeStamp = -1;
    }

    void Update()
    {
        //  受信データ更新
        OSCHandler.Instance.UpdateLogs();
        //  受信データ解析
        foreach (KeyValuePair<string, ServerLog> item in OSCHandler.Instance.Servers)
        {
            for (int i = 0; i < item.Value.packets.Count; i++)
            {
                if (lastTimeStamp < item.Value.packets[i].TimeStamp)
                {
                    lastTimeStamp = item.Value.packets[i].TimeStamp;

                    //  OSCアドレスを取得
                    string address = (string)item.Value.packets[i].Address;

                    //  受信した値を取得
                    string dataValue = (string)item.Value.packets[i].Data[0];

                    // 処理の振り分けの例
                    if (address == "/vvp")
                    {
                        Debug.Log("アドレスが/vvp、値が" + dataValue + "のデータを受信しました。");

                        // Androidアプリ側へデータを送信する
                        OSCHandler.Instance.SendMessageToClient("/unity", "vvpアドレスで受信できました。");
                    }
                    else
                    {
                        Debug.Log("アドレスが" + address +  "、値が" + dataValue + "のデータを受信しました。");
                    }
                }
            }
        }
    }
}

OSCHandler.Instance.Init();でOSCサーバとクライアントの機能を初期化
Updateメソッド内でAndroidアプリからのOSCデータを待ち受けます。
OSCHandler.Instance.SendMessageToClientでAndroidアプリにOSCデータを送信できます。
上記スクリプトでは受信したOSCのアドレスがvvpであったときにAndroidにOSCデータを送り返すように記述しています。

続いてAndroidアプリ側の設定

OSCの送受信はUDPの送受信ができれば可能なので様々なやり方があるかと思います。
例として動作確認できたオープンソースを紹介するにとどまらせていただきます。

  • ネイティブアプリ開発していればこちら JavaOSC
  • ionic,cordovaでの開発していればこちらcordova-plugin-osc

最後に

wifiにさえつながっていれば他の端末とのやり取りに、連携するアプリ以外の別途サーバーやクラウドサービスも必要ないのでOSCでのやり取りはお手軽なのが非常に良いなという印象でした。 どのくらいのデータをどの程度の間隔で送れるか等の検証はしていませんが、同一ネットワーク内のやり取りなので、データの送受信は非常に早く、音ゲーを作ったとしてもタイムラグは感じず作れるのでは無いかと思います。 Arduinoだとwifi接続できるESP8266等の安価に手に入るモジュールもあるのでアプリ+電子工作というプライベートでも遊べそうです。