Unity に Texture を Swift の Native Plugin から送る
- UnityのTextureのポインタをSwiftだけで作ったNative Pluginに渡して処理するの逆の話です
- ネイティブで作成した Texture を Unity へ送って表示させたい場合があります
- 例えば、macOS のスクリーンキャプチャの映像を Unity で表示させる事ができます
- macOS や iOS では、MTLTexture から Texture2D.CreateExternalTexture を使って Texture2D を取得可能です
今回のサンプル
- リポジトリはこちらです
- Swift だけで、Unity の iOS の Native Plugin を作る の内容をベースにしています
- macOS で、スクリーンキャプチャした結果を Cube のテクスチャに貼っています
unityでmacのデスクトップキャプチャできた! pic.twitter.com/x2AkZ6z6zF
— ふじき (@fzkqi) June 10, 2021
Texture2D.CreateExternalTexture
- Texture2D.CreateExternalTexture を使うことで、ネイティブのテクスチャオブジェクトから Unity テクスチャを作成できます
- iOS や macOS の場合は、ネイティブのテクスチャオブジェクトは MTLTexture です
- そこで、MTLTexture のポインタ、テクスチャの高さと幅を用意します
Unityの実装
Native Plugin の定義
- width と height のポインタを渡して、ネイティブに代入させます
- 戻り値として、MTLTexture のポインタを IntPtr として受け取ります
[DllImport("mcDesktopCapture")]
private static extern IntPtr mcDesktopCapture_getCurrentFrame2(ref int width, ref int height);
Texture を取得する
- 取得したポインタから、Texture2D.CreateExternalTexture を使って Texture を得て設定しています
int w = -1;
int h = -1;
IntPtr texturePtr = mcDesktopCapture_getCurrentFrame2(ref w, ref h);
Texture2D texture = Texture2D.CreateExternalTexture(w, h, TextureFormat.ARGB32, false, false, texturePtr);
Renderer m_Renderer = GetComponent<Renderer>();
m_Renderer.material.SetTexture("_MainTex", texture);
Swift の実装
-
@_cdecl
を付けて、C# で作成した関数を実装します - ref を UnsafeMutablePointer として、IntPtr を UnsafeMutableRawPointer として読み替えます
- width と height にテクスチャの大きさを設定します
- retain してテクスチャのポインタを返します
@_cdecl("mcDesktopCapture_getCurrentFrame2")
public func mcDesktopCapture_getCurrentFrame2(_ width: UnsafeMutablePointer<Int64>,
_ height: UnsafeMutablePointer<Int64>) -> UnsafeMutableRawPointer {
let texture: MTLTexture = getTexture()
width.initialize(to: Int64(texture.width))
height.initialize(to: Int64(texture.height))
return Unmanaged.passRetained(texture).toOpaque()
}
- 破棄が必要な場合は、takeRetainedValue を使います
@_cdecl("mcDesktopCapture_clearFrame")
public func mcDesktopCapture_clearFrame(_ texturePtr: UnsafeMutableRawPointer) {
_ = Unmanaged<MTLTexture>.fromOpaque(texturePtr).takeRetainedValue()
}
ライブラリの出力と設定
- こちらの記事の
Framework でビルドする
の章以降と同じ手順で実行ビルド可能です
- 作成した ライブラリ を Unity のプロジェクトにコピーして、Texture を取得できていることを確認します
おわりに
- Texture2D.CreateExternalTexture を使うことで、Swift だけで作ったライブラリから、Unity へ Texture を送る仕組みを実装できました
- CreateExternalTexture を関連する関数に、UpdateExternalTexture があり、Texture の作成だけでなく、更新も可能です
- Swift から Unity に Texture を送る仕組みは、応用の幅が広いので、活用して行きたいです