UnityのネイティブプラグインをGoで書く #golang #unity

May 11, 2016

この記事はQiitaの記事をエクスポートしたものです。内容が古くなっている可能性があります。

ネイティブプラグイン用のGoのコードを書く

以下のようなコードを用意し、hoge.goとしておきます。 どうやらmainパッケージでないとダメなようです。 cgo経由で関数をエクスポートするので、import "C"を書きます。 Hoge関数をエクスポートするために//export Hogeというコメントを書きます。

package main

import "C"

//export Hoge
func Hoge() int {
    return 100
}

func main() {
}

Androidのネイティブプラグインを作る

Android用に.soファイルを作ります。

$ CGO_ENABLED=1 \
CC=arm-linux-androideabi-gcc \
GOOS=android \
GOARCH=arm \
GOARM=7 \
go build -buildmode=c-shared -o libhoge.so hoge.go

作成した.soファイルをUnityに取り込みます。 Assets以下にPlugins/Android以下にできたlibhoge.soファイルを置きます。

iOSのネイティブプラグインを作る

クロスコンパイラを再ビルドしないといけないらしいので、$GOROOT/misc/iosにある通りに、make.bashを走らせます。なお、通常のGo(1.5以上)をソースからビルドする際と同じように$GOROOT_BOOTSTRAPも設定する必要があります。

※追記 以下の記事にGo Mobileのツールチェインを使う方法について書きました。 この方法であれば、ツールチェインをビルドし直す必要がありません。 http://qiita.com/tenntenn/items/11b2d08af6186b436422 —追記 終わり—-

$ cd $GOROOT/src
$ GOROOT_BOOTSTRAP=/path/to/go1.4/ \
GOARM=7 \
CGO_ENABLED=1 \
GOARCH=arm \
CC_FOR_TARGET=`pwd`/../misc/ios/clangwrap.sh \
CXX_FOR_TARGET=`pwd`/../misc/ios/clangwrap.sh ./make.bash

続いて、.aファイルを以下のように作ります。

CGO_ENABLED=1 \
GOARCH=arm \
go build -buildmode=c-archive -tags=ios hoge.go

hoge.aファイルができるので、それをUnityに取り込みます。 Assets以下にPlugins/iOS以下にできたhoge.aファイルを置きます。 hoge.hはなくてもビルドできるようです。

XCodeプロジェクトを出力した後に以下の設定を行います。

  • BuildSettings > Build Options > Enable BitcodeをNoにする
  • BuildSettings > Architectures > ArchitecturesをArm7だけにする。

試していませんが、Arm64用もビルドすれば、おそらく動くとは思います。

Unity側に呼び出すコードを書く

以下のようなコードを書くと呼び出せます。 うまく呼び出せていたら、n = 100とコンソールに表示されます。

using UnityEngine;
using System.Runtime.InteropServices;

public class Sample : MonoBehaviour
{

#if UNITY_IPHONE
    [DllImport("__Internal")]
#else
    [DllImport("hoge")]
#endif
    private static extern int Hoge();

    void Start()
    {
        var n = Hoge();
        Debug.LogFormat("n = {0}", n); // n = 100
    }
}

まとめ

UnityからGoで書いたネイティブプラグインを呼び出す方法について紹介しました。 net/httpなどの標準ライブラリは問題なく使えると思うので、通信部分をGoで書くということもアリなのではないかなと思います。 気になるのは、.soファイルや.aファイルの容量ですが、今回作った.soファイルについては1.1MBで.aファイルについては883KBでした。 go buildする際に-ldflags "-s"を指定して、シンボルテーブルを削ると、.soファイルは793KBまで減りました。 おそらく、.aファイルについても同様に軽くなると思います。

Go MobileのJavaバインドみたいにC#バインドを書けばもっと便利になりそうです。 また、UnityのネイティブプラグインはJavaやObj-Cでも書けるので、頑張ればgomobile bindで作ったGoのSDKも使えるとは思います。