1
1

AndroidアプリにUnity as a Libraryを導入する

Posted at

きっかけ

弊社で運用中のアバターを介してビデオ通話ができるSNSアプリがすべてUnityで実装されており、UI/UXのカスタムが非常に難しい状況でした。
そこでUaalを導入し、ビデオ通話中のアバターの表示やプロフィールアバターの表示等はUnity、それ以外のSNS機能やサーバーとの通信はネイティブで行うことで役割分担を進めようと方針が決まりました。

Unity as a Libraryとは

Unity as a Libraryとは、ゲームエンジンUnityで開発した機能をAndroidやiOSのNativeアプリにモジュールとして組み込む技術です

利用用途として、例えば3D描画のあるSNSアプリを作りたいとなったとします。Unityは3D描画部分の開発に強いですが、SNS部分は弱いです。逆にNativeはSNS部分の開発に強いですが、3D部分はそこまで強くありません。そのようなときに、Unity as a Libraryを使うと、3D部分は3Dに強いUnityで作り、SNS部分はNativeで作ることが可能になります。

このように、Unityが強い部分はUnityが作り、Nativeが強い部分はNativeでアプリを作ることが可能となります。

UnityからエクスポートとAndroidプロジェクトへのインポート

unityプロジェクトのexport後、出力されたunityLibraryをandroidにインポートするまでの手順は以下の記事を参考にしました。

今回はandroidの設定以降の手順を備忘録として残しておこうと思います。

設定

プロジェクト内でインポートしたUnityLibraryを扱えるように設定していきます。
それぞれのプロジェクトによって多少の違いがありますのでご理解ください。

build.gradle(:app)

dependenciesブロックに以下を追記します。

implementation project(':unityLibrary')
implementation fileTree(dir: project(':unityLibrary').getProjectDir().toString() + ('\\libs'), include: ['*.jar'])

defaultConfigにndkブロックを追記します。

ndk {
    abiFilters "armeabi-v7a", "arm64-v8a"
}

string.xml

xmlに以下を追記。
Unityから参照されているらしく、String.xmlに追加しないとクラッシュしました。

<string name="game_view_content_description">Game view</string>

gradle.propeties

以下の情報を追加

android.nonTransitiveRClass=true
org.gradle.jvmargs=-Xmx4096M
org.gradle.parallel=true
unityStreamingAssets=.bytes, .txt
unityTemplateVersion=3

setting.gradle

unityLibraryフォルダをAndroid Studioで認識できるようにするため、dependencyResolutionManagementの上に以下を追記。

include ':unityLibrary'
project(':unityLibrary').projectDir=new File('unityLibrary')

dependencyResolutionManagementブロック内でflatDirブロックを追加。

flatDir {
    dirs "${project(':unityLibrary').projectDir}/libs"
}

build.gradle(:unityLibrary)

特に修正は必要ありませんが、Unityのバージョンが古いと下記の修正が必要になるかもしれません。

  • namespaceを追記
  • repositoryブロックを削除
  • ndkパスの削除

ViewにUnityProjectを表示

AndroidアプリのViewにUnityのViewを表示していきます。
Viewの表示にはUnityPlayerのインスタンス化が必要になります。UnityPlayerはUnityの再生、停止、AndroidとUnityのデータのやり取りを管理するクラスです。
まずはUnityPlayerを管理するクラスをシングルトンで作成します。

class UnityManager private constructor() {

    private var unityPlayer: UnityPlayer? = null

    companion object {
        val shared = UnityManager()
    }

    // Unityを初期化する
    fun initializeUnity(context: Context) {
        if (unityPlayer == null) {
            unityPlayer = UnityPlayer(context as Activity)
        }
    }

    // Unityのビューを取得する
    fun getUnityView(): UnityPlayer? {
        return unityPlayer
    }

    // Unityを起動する
    fun startUnity() {
        unityPlayer?.onResume()
        LogUtils.debug("UnityManagerLog", "🚀 Unityを起動しました")
    }

    // Unityを停止する
    fun stopUnity() {
        unityPlayer?.onPause()
        LogUtils.debug("UnityManagerLog", "🚀 Unityを停止しました")
    }

    // Unityのウィンドウを表示する
    fun showUnity(boolean: Boolean) {
        unityPlayer?.requestFocus()
        unityPlayer?.windowFocusChanged(boolean)
        LogUtils.debug("UnityManagerLog", "🚀 Unityウィンドウを切り替えました")
    }

    // Unityにメッセージを送信する
    fun sendMessageToUnity(objectName: String, functionName: String, argument: String) {
        unityPlayer?.let {
            LogUtils.debug("UnityManagerLog", "Unityに送信するメッセージ: $objectName, $functionName, $argument")
            UnityPlayer.UnitySendMessage(objectName, functionName, argument)
        }
    }
}

Unityは最初の起動に数秒かかるため、ビデオ通話時にスムーズにUnityViewを表示できるよう、アプリ起動時にMainActivityであらかじめUnityPlayerを起動しておきます。

private fun initUnityPlayer() {
    UnityManager.shared.initializeUnity(this)
    UnityManager.shared.startUnity()
}

最後にFragment内でUnityViewを表示したいLayoutにaddします。
ちなみにshowUnityメソッド内にあるunityPlayer.windowFocusChanged()のメソッドを直前に呼ばないとUnityのViewは表示されません。(理由はよく分からないため有識者の方ご教授お願いします🙇)

val unityView = UnityManager.shared.getUnityView()
UnityManager.shared.showUnity(true)
binding.mainVideoGridLayout.addView(unityView)

ビルドが通り、UnityのViewが正常に表示されれば完成です!
他にもUnityPlayer.UnitySendMessageを使用すると、UnityとAndroidでデータのやり取りが可能です。

完成図
Screenshot_20240816-113718.png

最後に

情報が少ないこともあってか、導入から実際の運用に至るまでかなり時間がかかりました!

今回の開発を通して、Androidの設定周りが少し理解できました✌️
AndroidアプリにUaalを導入することがあれば参考にしてみてください。

参考

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1