🧬

Unity iOS・Androidプラグイン入門

2023/05/04に公開

UnityのiOS、Androidプラグインの作成の仕方を解説していきます。

  • 前提
    UnityのiOSとAndroidPlatformのインストールと,Xcode,AndroidStudioのインストールが必要です。

iOS

iOSプラグインはObjcベースで作成する手法が多く見られますが、今回はSwiftのみで完結する方法を解説していきたいと思います。

ステップは下記の通りです。

1 SwiftPackageManagerを作成
2 Swiftコードを書く。
3 C言語として公開
4 xcframeworkとして出力
5 Unityに組み込む。
6 iOSプラットフォームに変更してビルド

Step1 SwiftPackageManagerを作成

まず、SwiftPackageManager(SPM)を作成します。SPMに関しては詳細は解説しませんがこちらの動画を見ていただければイメージは掴めると思います。
https://www.youtube.com/watch?v=s1EIF-mUUD8

下記のコマンドを打ちます

swift package init --type=library --name=好きなパッケージ名

SPMを作成した後にXcodeで開きます。すると、Sourcesフォルダが作成されているので、ここにSwiftのコードを書いていきます。

Step2 Swiftのコードを書く

今回はプラグインの実装がメインなのでSwiftのコードは簡単にします。
Swiftのメソッドを定義します。

struct UnityiOSPlugin {
  static func ReturnInt() -> Int64 {
      return 111
  }
}

Step3 C言語として公開

c言語の関数としてUnityで使用したい関数を公開します。

@_cdecl("swiftPmPlugin_ReturnInt")
public func swiftPmPlugin_ReturnInt() -> Int64 {
   return UnityiOSPlugin.ReturnInt()
}

今回はIntを送るだけの最小限の実装です。文字列など送る際はC言語の型に変換してから送る必要があります。

Step4 xcframeworkとして出力

SPMをxcframeworkとしてビルドするには下記の方法をお勧めします。
https://nnsnodnb.hatenablog.jp/entry/swiftpm-build-xcframework
https://github.com/unsignedapps/swift-create-xcframework

既出の記事を参考にswiftpm-build-xcframeworkをインストールして使用します。(mintを使用していない場合はmint runは必要ありません。)

mint run swift-create-xcframework --clean SPM名 --output 出力先フォルダ --platform ios

指定したフォルダ配下にxcframeworkが作成されていれば成功です!

Step5 Unityに組み込む

UnityプロジェクトのAsset配下にPlugin->iOSフォルダを作成します。

xcframework内のframeworkをiOSフォルダ配下にいれます。

自分の手元では検証していないのですが、xcframeworkをそのまま組み込むこともできると思います。ここら辺は下記のforumが参考になりそうです。
https://forum.unity.com/threads/how-do-i-add-xcframwork-from-code.840163/

frameworkのInspectorのAdd To Embedded Binariesにチェックを入れます。
これをすることで、Xcodeプロジェクトを作成する際にframeworkが自動でEmbedされます。
補足するとEmbedするということはプロジェクトの内部バンドルとして認識されるということです。
作成したframeworkをDynamicリンクしたいのでEmbedするようにします。

実際にiOSのメソッドを使用するためのスクリプトを作成します。公開したメソッド名を宣言し、[DllImport("_Internal")]属性をつけます。

  public class iOSNative : MonoBehaviour
{

    [DllImport("__Internal")]
    private static extern long 公開したメソッド名();
    void Start()
    {
        Debug.Log(公開したメソッド名() + "確認");
    }      
}

DLLはDynamic link libraryのことで、これは外部で実装されたDLLをimportすることを指します。
InternalはiOS特有のもので静的にリンクされたライブラリを宣言するのに使用します。

正直ここら辺のInternelの内部挙動は分かっていないです。
下記画像で作成したframeworkはDynamiclinkになっているみたいですし、XcodeprojectにEmdedする必要があるということはDynamiclinkのはずだと思っていました。ただ、Unity側から使うときは静的にリンクされたライブラリとして使用するようです?? どういうことか分かっていません。

Step6 iOSプラットフォームに変更してビルド

File => BuildSetting => iOSにビルドするプラットフォームを切り替えてビルドします。

スクリプトで定義したメソッドが呼び出されいれば成功です。

もしかしたらBitCode周りでエラーになるかもしれないので下記記事の通りに修正するとビルドできるはずです。
https://qiita.com/temoki/items/92999fcede0a7b89760f

Android

続いてAndroidプラグインを作成します。
Androidに関しては予備知識があまりないので下記の記事とほとんど同じ方法です。
https://gaprot.jp/2020/03/30/unity-android-native-plugin/

ステップは下記の通りです。

1 空のプロジェクトを作成
2 AndroidLibraryのModuleを作る
3 classes.jarを追加する。
4 Javaコードを書く
5 arrとして出力
6 Unityに組み込む。
7 Androidプラットフォームに変更してビルド

Step1 空のプロジェクトを作成

Android Studioを立ち上げてNo Activityを選択してプロジェクトを作成します。言語はJavaを選択します。

Step2 AndroidLibraryのModuleを作る

File -> New Module -> AndroidLibraryを作成します。

作成後、Project Structureから使用しないappモジュールを削除します。

Step3 classes.jarを追加する。

Unityのクラスライブラリを入れる必要があるので下記のPathにあるclasses.jarをAndroidプロジェクトのlibs配下に入れてあげます。

Unityのpath/PlaybackEngines/AndroidPlayer/Variations/mono/Release/Classes/classes.jar

Androidプラグインの中にクラスライブラリを入れたままにするとUnity側でエラーを吐くのでbuild.gradleの部分に compileOnly fileTree(dir: 'libs', include: ['*.jar'])を追加して、Javaのコンパイルのみで使用するようにします。

dependencies {

   implementation 'androidx.appcompat:appcompat:1.4.0'
   compileOnly fileTree(dir: 'libs', include: ['*.jar'])
   testImplementation 'junit:junit:4.+'
   androidTestImplementation 'androidx.test.ext:junit:1.1.3'
   androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

step4 Javaコードを書く

Javaファイルを作成。(画像ではUnityAndroidPlugin)ここに使用したいコードを書きます。

今回はiOSと同様簡単な実装にしました。

Step5 arrを出力する

Build -> Make Module でModuleを実際にビルドします。
するとModuleフォルダ配下にarrが出力されます。

プロジェクト名/モジュール名/build/outputs/aar

自分はこれでビルドする際に下記のAPIレベルのエラーを吐いたのでダウングレードすることで対応しました。
https://unluckysystems.com/【android-studio】ビルド時にエラーinstalled-build-tools-revision-31-0-0-is-corrupted-remove-and-install-again-using-the-sdk-manag/

Step6 Unityに組み込む

Assetー>Plugin->Androidにarrを入れます。

UnityからAndroidを使用するにはAndroidJavaObjectが必要になります。

public class AndroidNative : MonoBehaviour
{
    private AndroidJavaObject _plugin;
    private const string PackageName = "com.example.mylibrary";
    private const string ClassName = "UnityAndroidPlugin";
    
    void Start()
    {
       _plugin = new AndroidJavaObject($"{PackageName}.{ClassName}");
       Debug.Log(_plugin.Call<int>("ReturnInt"));
    }

    private void OnDestroy()
    {
       _plugin.Dispose();
       _plugin = null;
    }
}

Step7 Androidプラットフォームに変更してビルド

File->BuildSetting -> Androidを選択してSwitching Platformをして、buildします。
指定したフォルダにapkファイルが出力されるので、これを元にアプリを端末にインストールしてください。初めてAndroidビルドする際は下記の記事が参考になります。

https://tech.pjin.jp/blog/2022/02/08/unity-rungame-24
実機を持っていない方はapkファイルでアプリをエミュレーターにインストールする必要があります。
この記事を参考にするとスムージにできると思います。
https://codeforfun.jp/android-studio-how-to-install-apk-using-adb-commands/

まとめ
Androidは以外とエラーでちょこちょこ詰まることが多く時間がかかりましたが、出来てよかったです!
最後まで読んでいただきありがとうございました🙇

実装repository
https://github.com/katomizuki/UnityiOSandAndroidNativePluginBase

Discussion