01.Unity側で作成したテクスチャを、Java側でGL_TEXTURE_EXTERNAL_OESのテクスチャとしてSurfaceTextureに割り付けて使用する方法
結果としては、失敗。この方法はうまくいかなかった。
事象としては、glBindTexture() で GL_INVALID_OPERATION エラーが発生する。
考察としては、「Unityで作成したテクスチャは、GL_TEXTURE_2D をターゲットとして作成されているため、異なるターゲットである GL_TEXTURE_EXTERNAL_OES
での glBindTexture() でエラーが発生する」と考える。
解説
Android(Java)のSurfaceTextureのテクスチャをUnityで描画するために、最低限すべきことは、以下です。
- AndroidStudioを使用し、Androidライブラリを作成します。Androidライブラリに、Java側の処理記述します。
- Unityを使用し、Unityアプリを作成します。Unityアプリに、Unity側の処理を記述します。
Unity側で作成したテクスチャを、Java側でGL_TEXTURE_EXTERNAL_OESのテクスチャとしてSurfaceTextureに割り付けて使用するために、すべきことは、以下です。
- Java側の処理として、「Unity側で作成したテクスチャを、GL_TEXTURE_EXTERNAL_OESのテクスチャとしてバインドし、SurfaceTextureに割り付ける処理」を記述します。
- Unity側の処理として、「Unityのテクスチャを作成し、作成したテクスチャIDを、Java側の処理に渡す処理」を記述します。
実装
Androidライブラリのプロジェクトの作成
まず、AndroidStudioを使用し、Androidライブラリを作成します。
Androidライブラリのプロジェクトを作成します。
(開発環境としては、Android Studio 4.2.2 を使用しています)
(この設定でプロジェクトを作成しなければいけない、というわけではありません。)
「Welcome to Android Studio」画面の「Create New Project」をクリックします。
「New Project」ウィンドウが表示されます。
「No Activity」を選択し、「Next」ボタンを押します。
Nameに、プロジェクト名を入力します。たとえば、「SurfaceTextureRendererProject」と入力します。
Package nameのドメイン部分に、会社のドメイン名を指定します。
Save locationに、プロジェクトを保存するフォルダパスを指定します。
「Finish」ボタンを押します。
しばらく待ちます。
Android Studio のステータスバーに「Gradle sync finished in ・・・」や「*daemon started successfully ・・・」と出るまで待ちます。
Androidライブラリのプロジェクトができました。
Androidライブラリモジュールの作成
Androidライブラリモジュールを追加します。
メインメニュー「File > New > New Module」を選択します。
「Create New Module」ダイアログが表示されます。
「Android Library」を選択します。
Module nameに、モジュール名を入力します。たとえば、「surfacetexturerenderer」と入力します。
Package nameのドメイン部分に、会社のドメイン名を指定します。
Minimum SDKを選択します。たとえば、「API 19: Android 4.4 (KitKat)」を選択します。Unityで作成するアプリのMinimum API Levelのバージョンと一致させます。
「Finish」ボタンを押します。
しばらく待ちます。
Android Studio のステータスバーに「Gradle sync finished in ・・・」や「*daemon started successfully ・・・」と出るまで待ちます。
ライブラリモジュールができました。
Javaクラスの追加
Androidライブラリモジュールに、Java側の処理を記述するクラスを追加します。
「Project」ウィンドウの「surfacetexturerenderer > java > {ドメイン}.surfacetexturerenderer」を右クリックします。
右クリックメニュー「New > Java Class」を選択します。
「New Java Class」ダイアログが表示されます。
クラス名に、「SurfaceTextureRenderer」と入力します。
エンターキーを押します。
「OK」ボタンを押します。
SurfaceTextureRenderer.javaの内容を以下のようにします。
Androidライブラリモジュールのビルド
Androidライブラリモジュールをビルドします。
「Gradle」ウィンドウの「SurfaceTextureRendererProject > surfacetexturerenderer
> Tasks > build > build」をダブルクリックします。
モジュールのビルドが開始します。
しばらく待ちます。
Android Studio のステータスバーに「Gradle build finished in ・・・」と出るまで待ちます。
「{Androidプロジェクトフォルダ}\{Androidライブラリモジュール名}\build\outputs\aar」フォルダに、リリースビルド、デバッグビルドの2つの「aar」ファイルが生成されます。
Unityアプリのプロジェクトの作成
ここからは、Unityを使用し、Unityアプリを作成します。
Unityアプリのプロジェクトを作成します。
(開発環境としては、Unity 2020.3.12f1 を使用しています)
(この設定でプロジェクトを作成しなければいけない、というわけではありません。)
「Unity Hub」画面の「プロジェクト」「新規作成」をクリックします。
「新しいプロジェクトを作成」ウィンドウが表示されます。
「3D」を選択します。
プロジェクト名欄に、プロジェクト名を入力します。たとえば、「RenderingSurfaceTextureInUnity」と入力します。
保存先に、プロジェクトを保存するフォルダパスを指定します。
「作成」ボタンを押します。
しばらく待ちます。
Unityアプリのプロジェクトができました。
Build Settingsの設定の変更
Build Settingsの設定を変更します。
メインメニュー「File > Build Settings」を選択します。
「Build Settings」ダイアログが表示されます。
「Scenes In Build」の「Add Open Scenes」ボタンを押し、現在開いているシーンを「Scenes In Build」に追加します。
「Platform」の「Android」を選択します。
「Switch Platform」ボタンを押します。
しばらく待ちます。
Unityアプリの対象プラットフォームがAndroidになりました。
「Build Settings」ダイアログを閉じます。
Project Settingsの設定の変更
Project Settingsの設定を変更します。
メインメニュー「Edit > Project Settings」を選択します。
「Project Settings」ダイアログが表示されます。
左側の設定項目の「Player」を選択します。
Company Name欄に、会社名を入力します。
Graphics APIs欄の「+」ボタンから「OpenGLES2」を追加します。
Graphics APIs欄の「OpenGLES2」以外を削除します。
Multithread Renderingのチェックを外します。
Package Nameが、Company Name欄に入力した会社名が反映されたパッケージ名になります。
Minimum API Levelを選択します。たとえば、「Android 4.4 'KitKat' (API level 19)」を選択します。Android Studioで作成したAndroidライブラリのMinimum
SDKのバージョンと一致させます。
「Project Settings」ダイアログを閉じます。
Android Logcatのインストール
アンドロイド端末で動作させた際の出力ログを確認するために、Android Logcatをインストールします。
メインメニュー「Window > Package Manager」を選択します。
「Package Manager」ダイアログが表示されます。
ダイアログ左上のPackage表示フィルタを「Packages: In Project」から「Packages: Unity Registry」に変更します。
検索ワード欄に「logcat」と入力し、で検索します。
「Android Logcat」を選択します。
「Install」ボタンを押します。
しばらく待ちます。
「Android Logcat」がインストールされました。
「Package Manager」ダイアログを閉じます。
続いて、「Android Logcat」の出力ログを表示するウィンドウをUnity画面に配置します。
メインメニュー「Window > Analysis > Android Logcat」を選択します。
「Android Logcat」ウィンドウが表示されます。
「Android Logcat」ウィンドウをUnity画面の適当な場所に配置します。
UIアイテムの追加
Unityのシーンに、テクスチャを表示するための画像要素、処理をトリガーするためのボタン要素を追加します。
「Hierarchy」ウィンドウにて、何も選択せず右クリックします。
右クリックメニュー「UI > Panel」を選択します。
「Canvas」が追加され、「Canvas」の下に「Panel」が追加されます。
(「EventSystem」も追加されます。)
「Hierarychy」ウィンドウの「Panel」を右クリします。
右クリックメニュー「UI > Raw Image」を選択します。
「RawImage」が追加されます。
「Hierarychy」ウィンドウの「Panel」を右クリします。
右クリックメニュー「UI > Button」を選択します。
「Button」が追加されます。
続いて、追加したUI要素のサイズ、位置を設定します。
PanelのScaleを、X = 0.75、Y = 0.75、に設定します。
RawImageのサイズを、Width = 512、Height = 512、に設定します。
Buttonの位置を、PosX = 0、PosY = -300、サイズを、Width = 320、Height = 60、に設定します。
Sceneウィンドウを正面から表示したときの、UI要素の配置イメージ
aarファイルの配置
Androidライブラリモジュールのファイル(aarファイル)を、Unityアプリのプロジェクトに配置します。
Unityを一度閉じます(シーンを保存していない場合は、シーンを保存し、Unityを終了します)。
「{Unityプロジェクトフォルダ}\Assets」フォルダの下に「Plugins」フォルダを作成し、その下に「Android」フォルダを作成します。
「{Unityプロジェクトフォルダ}\Assets\Plugins\Android」フォルダに、
「{Androidプロジェクトフォルダ}\{Androidライブラリモジュール名}\build\outputs\aar」フォルダに生成済みの「aar」ファイルのリリースビルドの方を、コピ-します。
Unityでプロジェクトを再度開きます。
「Project」ウィンドウにて、「Assets > Plugins > Android」に、「aar」ファイルが配置されていることを確認します。
C#スクリプトの追加
Unity側の処理を記述するc#スクリプトを追加します。
「Project」ウィンドウにて、「Assets」フォルダの下に「Scripts」フォルダを作成します。
「Scripts」フォルダの中に、「C# Script」を追加し、名前を「RawImageScript」に変更します。
RawImageScriptの内容を以下のようにします。
C#スクリプトのUI要素への割り付け
C#スクリプト「RawImageScript」をUI要素「RawImage」に割り付けます。
「Project」ウィンドウのC#スクリプト「RawImageScript」を、「Hierarchy」ウィンドウの「RawImage」にドラッグ&ドロップします。
「Inspector」ウィンドウにて、「RawImageScript」が「RawImage」に割り付いたことを確認します。
ボタンを押したときに実行する関数の設定
ボタンを押したときに実行する関数を設定します。
「Hierarchy」ウィンドウの「Button」を選択し、「Inspector」ウィンドウの表示内容を「Button」にします。
「Hierarchy」ウィンドウの「RawImage」を、表示内容が「Button」になっている「Inspector」ウィンドウの「OnClick()」のオブジェクト欄にドラッグ&ドロップします。
「OnClick()」のFunction欄を、「RawImageScript.OnEvent」にします。
「ボタンをクリックすると、『RawImage』オブジェクトに割り付けられた『RawImageScript』スクリプトの『OnEvent』関数が実行される」ようになりました。
Build
メインメニュー「File > Build Settings」を選択します。
「Build Settings」ダイアログが表示されます。
「Build」ボタンを押します。
出力フォルダと、出力ファイル名を指定します。たとえば、出力フォルダとして、Unityアプリのプロジェクトフォルダの下に「Build」フォルダを作成、指定し、出力ファイル名として「RenderingSurfaceTextureInUnity.apk」と指定します。
「保存」ボタンを押します。
Unityアプリのビルドが開始します。
しばらく待ちます。
Unityアプリの実行ファイル(apkファイル)が生成されます。
「Build Settings」ダイアログを閉じます。
実行
Build And Run
Android端末をUSB接続しておきます。
メインメニュー「File > Build And Run」を選択します。
Unityアプリのビルドが開始し、ビルドが終了すると、Android端末上でUnityアプリが実行されます。
起動直後
アプリ画面のボタンを押します。
TextureRendererの初期化処理が実行されます。
「Android Logcat」ウィンドウを確認すると、glBindTexture() でエラーが発生しています。
アプリ画面のボタンを再度押します。
テクスチャの更新処理が実行されます。
UnityアプリのRawImageの描画に変化はありませんでした。
「Android Logcat」ウィンドウを確認すると、SurfaceTexture#updateTexImage() で、エラーが発生しています。
考察
アプリ画面のボタンを1回目に押した際のエラーのエラーコードは1282。エラーコード 1282 (16進数表現にすると0x502)は、GL_INVALID_OPERATION。
glBindTexture()関数のリファレンスによると、
「GL_INVALID_OPERATION is generated if texture was previously created with
a target that doesn't match that of target.」
「Unityで作成したテクスチャは、GL_TEXTURE_2D をターゲットとして作成されているため、異なるターゲットである GL_TEXTURE_EXTERNAL_OES
での glBindTexture() でエラーが発生する」と考える。
アプリ画面のボタンを2回目に押した際のエラーは、1回目に押した際のエラーと関係のあるエラーと考える。
関連ページ
次項目:02.Unity側で作成したテクスチャを、Java側でGL_TEXTURE_2DのテクスチャとしてSurfaceTextureに割り付けて使用する方法