Unity iOS のネイティブプラグインを Swift で書いた
Unity iOS のネイティブプラグインを Swift で書く。 と言っても、Unity から直接呼び出される部分は Objective-C++ で書くことになるので、 Objective-C から Swift を呼び出すのと基本変わらない。
概要
- Swift のクラスを Objective-C に公開する
- Objective-C++ から Swift のクラスを使う
- Swift から C の関数を使う
環境
- Unity 5.3.4f1
- Xcode Version 7.3.1 (7D1014)
基本的なこと
- Using Swift with Cocoa and Objective-C (Swift 2.2): Swift and Objective-C in the Same Project
- Using Swift with Cocoa and Objective-C (Swift 2.2): Interacting with C APIs
Swift のクラスを Objective-C に公開する
Build Option で Embedded Content Contains Swift Code が Yes になっていれば、ビルドの度に ProductName-Swift.h
が生成される。
以下の条件を満たせば、Swift で書いたクラスが Swift.h に追加されるので、Objective-C から呼び出せるようになる。
- クラスは NSObject を継承する
- クラスおよびメソッドのスコープを public にする
今回は、questbeat/QBImagePicker: A clone of UIImagePickerController with multiple selection support. を使って、 アルバムから画像を選択するプラグインを書いてみた。
公開できたところを Swift.h から一部抜粋すると以下のような感じ
Objective-C から呼び出すために public にするのは、Objective-C から直接呼び出したいクラスおよびメソッドだけで良い。 (クラスが public になったことが原因で、メソッドも public にする必要がある場合はまた別の話とする)
Objective-C++ から Swift のクラスを使う
Swift.h を #import
すれば、Objective-C のクラスのように呼び出すことができる。
「Objective-C++ から」と書いているが、Objective-C から使うのと特に変わったことはない。
ProductName-Swift.h に QBImagePickerDelegate
の forward declaration が追加できなかったので、明示的に #import
している。ここなんとかしたい。
Swift から C の関数を使う
プラグインを書くために UnitySendMessage
とか UnityGetGLViewController
とかを使いたい。
Swift から C の関数を使うために、
- Bridging Header を定義する
- Swift Compiler の Objective-C Bridging Header にヘッダーのパスを指定する
が必要。
ということで、これらをやってくれる dddnuts/Unifty: Bridge Swift and Objective-C for Unity native plugins というパッケージを作った。
Unifty を使うと、Unifty.SendMessage
みたいな感じで Unity プラグインの関数を呼ぶことができる。
クライアントから Bridge を意識しなくて良いように、Unifty クラスで wrap している。
Bridge との型変換があれば、Unifty クラス内で吸収する。
C の const char *
は Swift の UnsafePointer<Int8>
になるので、String
から変換が必要かと思ったが、そこはやってくれるっぽい。
まとめ・感想
- public な Swift のクラスを定義して Objective-C から呼び出せるようにした
- Objective-C++ から Swift のクラスを使うコードを書いてみた
- Swift から C で書かれた Unity プラグインの 関数を使うために、Bridging Header を書いた
- Bridging Header の設定を Unifty というパッケージにして公開した
Swift で書けるなら Swift で書きたいので Unity でも Swift でネイティブプラグインを書けるのはうれしい。 Objective-C と Swift を一緒に使うのが思っていた以上に簡単ですごいと思った