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)

基本的なこと

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 から一部抜粋すると以下のような感じ :point_down:

Objective-C から呼び出すために public にするのは、Objective-C から直接呼び出したいクラスおよびメソッドだけで良い。 (クラスが public になったことが原因で、メソッドも public にする必要がある場合はまた別の話とする)

Objective-C++ から Swift のクラスを使う

Swift.h を #import すれば、Objective-C のクラスのように呼び出すことができる。 「Objective-C++ から」と書いているが、Objective-C から使うのと特に変わったことはない。

:warning: 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 を一緒に使うのが思っていた以上に簡単ですごいと思った :apple:

参考