ロバメモ - 素人のUnity覚書と奮闘記

素人のUnity覚書と奮闘記

WebGLからFirebaseのデータを取得できるようにしたい

やりたいこと

WebGLでFirebaseを使いたい。
今回は、csからFirebaseのデータを取得できるようにする方法をメモ。

環境

Unity2018.2
WebGL
C#

前提

JavascriptでFirebaseが使える状態にしてあることが前提。  

仕組み

ちゃんと理解してるわけではないので、たぶんこんな感じだろうって感じで書いてます。
f:id:nico-taniku:20191225194644p:plain:w500
WebGLを載せるHTMLのhead部分でFirebaseのSDKの読み込みと初期設定をしておく。このSDKを利用してFirebaseにアクセスする。
Firebaseがらみの処理は、基本Javascriptで書くことになるので(FirebaseのSDKJavascript用を入れているので)、jslibという拡張子のファイルに書いてDllImport属性を使ってcsからjslibで定義したメソッドにアクセスできるようにする。
Firebaseからデータを取得したい場合は、jslibで定義したメソッドに戻り値を設定する方法でも良さそうだけど、私はSendMessageでcsへ送信する方法にした。

HTML側の処理

Firebaseが使える状態にしてあることが前提なので、詳細は割愛。

C#からjavascriptを実行するには

jslib側の処理

テキストエディタで新規作成して以下を書き込む。

(1)mergeIntoで全体を囲む
mergeInto(LibraryManager.library, {
    //ここに関数を定義
});
(2)関数を定義する
関数名: function(引数){ },

※関数を複数書く場合は , (カンマ)で繋げて書く。

書き方の例

mergeInto(LibraryManager.library, {

  ConsoleLog: function(message) {
    console.log("%c" + Pointer_stringify(message), "color:blue");
  },

});
(3)jslibを保存する

テキストに.jslibという拡張子をつけて、Unityの Assets / Plugins / WebGL / に保存する。
名前は任意でOK。下の画像の例では、LoadDataBase.jslib
f:id:nico-taniku:20191225201941p:plain:w300

cs側の処理

DllImportを書く

jslibで定義した関数を呼び出す呪文を唱えましょう。笑
(1)using System.Runtime.InteropServices;を書く。
(2)[DllImport("__Internal")]属性をつけたメソッドを作る。
(3)メソッドはstatic externにする。
(4)メソッド名・戻り値・引数は、jslibの関数と同じにする。

using System.Runtime.InteropServices;

public class LoadDataBase : MonoBehaviour
{
    [DllImport("__Internal")]
    static extern void ConsoleLog(string logString);
}
DllImportって何?

実は、この呪文の意味を理解していない。苦笑
DLLとは、ダイナミック リンク ライブラリの略らしい。共有ライブラリとも言われており、複数のプログラムで同時利用できるライブラリのことを指すらしい。
この場合は、FirebaseとUnityで共有するライブラリ=jslibファイルってことなのかな?
Importは輸入する・持ち込むといった意味なので、csに共有ライブラリを取り入れるって感じだろうか。
"__Internal"は、静的にリンクしたライブラリに使われる値のようだけど、DLL=ダイナミックってことは動的なのに、値で静的を指定するのがよくわからない。
そもそも動的リンク・静的リンクがわかってない。笑 いろいろ拾い読みしてみたけど、こういう感じかな?

静的リンク・・・あらかじめプログラムファイルに組み込んでいるライブラリ場合。
動的リンク・・・プログラム実行中に生成されるライブラリの場合。

プログラム上でcsに組み込むので動的リンク(DllImport)だけど、読み込むファイルは静的リンク(jslibはアセットにあるので)なので、[DllImport("__Internal")]ってなるのかな?

DllImport属性をつけると、static externにしないとエラーが出る。
static・・・静的。最初に定義した状態を維持するので、途中で内容が変わることはないよって感じかな。
extern・・・定義は別の場所でしてるので、ここでは宣言だけねって意味らしい。

定義と宣言の違いは、こんな感じかな?
定義・・・中身も含めて作られたもの。
宣言・・・ここに作りまーす!とスペースを確保した状態で中身はなし。
参考:C言語のグローバル変数とexternについて - Gobble up pudding

今回は、jslibで定義された関数をcsで宣言したってことかな。

Firebaseからデータを受け取るには

cs側の処理

SendMessageの受け子メソッドを作る。
・メソッド名は、jslibのSendMessageで指定した名前にすること。
・引数も、jslibのSendMessageで指定したデータ型にすること。

書き方の例

using System.Runtime.InteropServices;

public class LoadDataBase : MonoBehaviour
{

    [DllImport("__Internal")]
    static extern void GetUID();

    public void LoadUid(string str)
    {
        Debug.Log(str);
    }
}

シーンでの処理

jslibで指定したゲームオブジェクト名にして、csファイルをアタッチする。
f:id:nico-taniku:20191226112209p:plain:w300

jslib側の処理

書き方

SendMessage('シーンに配置したゲームオブジェクト名' , 'メソッド名' , '渡したいデータ');

使用例

mergeInto(LibraryManager.library, {

  GetUID: function () {
    var user = firebase.auth().currentUser;
    SendMessage( 'LoadDataBase', 'LoadUid', user.uid+','+user.displayName );
  },

});

参考

WebGL: ブラウザースクリプトとの相互作用 - Unity マニュアル