ダーク/ライト切り替え

【Unity】Go言語でDLLをビルドしてUnityからネイティブプラグインとして呼び出す【備忘録】

投稿日2022-11-05

Picture of the logo


目次

目次を読み込み中...

Go言語で書いたモジュールをUnityのC#スクリプトから呼び出すまでの方法を紹介します。初めて試してみて若干手間取った部分があるので備忘録も兼ねて書き残しておきます。内容は高度な事はしてません。初心者、初めての人向けです。

# 前提

  • ・ Windows環境を想定。Macの人は適宜置き換えてください。
  • ・ [Go言語](https://go.dev/)の開発環境は別途インストールする必要がある。
  • ・ [Mingw64](https://www.mingw-w64.org/)がビルドするために別途インストールする必要がある。
  • ・ GOPATHやMingw64のpathなどを事前に通してある。 AndroidやiOS向けにビルドする方法は既に他の人のブログがあるので、そちらを参照して下さい。 DLL化してエディター上で実行する記事が見当たらなかったので、ここではUnityエディター上での実行を確認するまでとさせていただきます。。

# 変数の型について

Go言語やC#に限った話ではなく、異なる言語間でデータのやり取りをする場合、その変数の型はプリミティブ型しか使えない事がほとんどです。

プリミティブ型とは最も基本的な型で、int float char byte bool などで言語によって異なります。Vector3などもそのままでは他言語には渡せないので、float x,float yなどに分解してやる必要があります。プリミティブ型の変数、関数は特段難しい事はないので割愛します。

ここではstring型のやり取り、厳密にはstring型の引数、戻り値をUnity~Go言語で受け渡しする方法を紹介します。

# C#のstringとGo言語のstringは違う

C#にもGo言語にもstring型が存在しますが、 func GetSampleText(text string) string {・・・} のようにGo言語側で定義して、Unity C#側で private static extern string GetSampleText(string text); と呼び出しても動作しません。エラーも出ません。多くの場合暴走したり落ちます。 これはC#のstringとGo言語のstringは一見名前が同じでも実はGoStringという型が適用されていて内部での形が微妙に違うからです。C#の文字列を正しくGo言語に渡したければ方法はいくつかあると思いますが、例として

のようにchar型(の配列)のポインタを受け渡しする必要があります。

# Go言語でWindows DLLをビルドする

go build -buildmode=c-shared -o hoge.dll hoge.go

ターミナルで上記のように打ち込んでビルドする。.dllと.hの二つが出力されるがUnityで必要なのはdllだけなのでdllファイルをUnityエディターのAssets-Pluginsフォルダにコピーする。 dllは一度でも実行されると変更も削除も出来なくなるので、一度でもPlayボタンを押してテスト実行させた後はdllを変更するには一度Unityを終了して再実行する必要があります。

# Unityで呼び出し用のC#スクリプトを作る

呼び出すUnity側では、

のようなスクリプトを作ります。なるべく戻り値もstring型で取得したかったけど面倒だったので一旦挫折しました。 unsafe private static extern byte* GetSampleTest(string text);

元はcharポインタですが、あとでbyteポインタとして使うのでUnity側では初めからbyteで定義しておきます。

またUnityでポインタを使うにはunsafeを入れて宣言しなければいけないし、事前にUnityエディターでunsafeの設定にチェックを入れる必要があります。

unsafeCheck

またGO言語には全角文字にUTF8が使用されるので、 System.Text.Encoding.UTF8.GetString(p, _maxLength)

のようにエンコードする必要があります。maxLengthは好きな数字でOK。

実行するとこのようになります。

result

# 結論

C# ~ Go言語の間で文字列データの受け渡しは一応可能ではあるけどunsafeは使わずに、なるべく直接文字列を避けてシリアライザとか上手く使うなり他の手を用いる方が良いと思います。

以上、初めてUnity-Go言語のネイティブプラグイン作成で手こずった部分を纏めてお行きました。世間で需要があるかはわかりませんが・・・






関連記事

GO言語サーバーとUnityクライアント(C#)をgRPCで接続テストしてみた【入門レベル】

blog

UnityでgRPCをする場合、Magic Onionを使うのがお手軽ですが、今回はGO言語でサーバーを構築してみたかったので最低限の接続機能を自作してみました。備忘録を兼ね書き残しておきます。

【Unity】MagicOnionサーバを立ち上げて自己証明書でSSL通信してみる

blog

Unity向けgrpcサーバーManicOnionの導入時にSSL化やNGINXの設定に少し手こずったので備忘録も兼ねて手順をまとめておきました。

UNITYからMYSQLデータベースにアクセスする【初心者向け】

blog

UnityからMySQL等のデータベースにアクセスする簡単なサンプルプログラムを紹介します。若干Java Scriptの知識も必要になります。

【Unity X Node.js】クライアント~サーバー間でAES暗号通信してみた

blog

Unityの暗号ライブラリCryptgraphyを使って暗号通信してみたかったので試してみました。

UNITYで扇形を作ってみた

blog

Unity上で扇形を作る機能が標準ではついてない?ようなので自作してみました。

Unity】一枚のイメージ画像を縦横のタイル状に分割する方法

blog

UnityのUGUIを使用して、一枚のイメージ画像を縦横に分割して表示する方法を紹介します。

【Unity】セーブデータの改ざんやチート対策を考えてみる

blog

ゲーム開発者にとって、チートは永遠の悩みです。どんなに対策しても開発者とチーターは「いたちごっこ」です。今回は初歩的な手段ではありますが、CRCやSHA256といった技術を使ってデータの改ざん、チート行為を検出する方法を紹介します。

UnityでTrail Rendererを使ってオブジェクトの軌跡を描画する

blog

今回はUnityでTrail Rendererを使ってオブジェクトの軌跡を描画する方法についてご紹介します。Trail Rendererを使うことで、オブジェクトがどのような軌跡を描いたかを可視化することができます。

【Unity】Json,CSVファイルを相互に変換する方法【備忘録】

blog

個人的備忘録も兼ねてUnityでインスペクタ上でテキストファイルを指定して、そのファイルから結果を取得する方法をいくつか紹介します。

FirebaseStorageからUnityへファイルを読み込み、Resourcesに保存する

blog

UnityでFIREBASEのStorageサービスから画像ファイルをダウンロードしてシーン上に表示、保存するまでの簡単な手順紹介です。


スポンサーリンク

このサイトをシェアする