UnityのiOSプラグインの作成
UnityのiOSプラグインの作成をまとめました。Unity 2019では不具合で動かなかったので、Unity 2020.1を使ってます。
・Unity 2020.1.0b.3837
1. UnityのiOSプラグインの作成
UnityのiOSプラグインを作成することで、UnityからiOSのネイティブ機能を利用できるようになります。
Unityプロジェクトに「iOSプラグイン」を追加し、Unityから「iOSプラグイン」の関数を呼び出します。さらに「iOSプラグイン」から、Swiftコードを呼び出すことができます。
2. はじめてのiOSプラグイン
はじめに、「Hello Swift!」という文字列をデバッグ出力するSwiftコードを呼び出す「iOSプラグイン」を作成します。
Unityプロジェクトを作成してください。
(1) Swiftコードの準備
UnityプロジェクトのAssets直下にPlugins/iOSフォルダを作成し、以下のファイルを配置します。
・Assets/Plugins/iOS/Sample.swift
import Foundation
@objc public class Sample : NSObject {
@objc public static func hello() {
print("Hello Swift!")
}
}
「iOSプラグイン」からアクセスするSwiftコードの条件は、次のとおり。
・ クラスは NSObject を継承。
・ 公開するクラス・メソッドに @objc を付ける。
・ 公開するクラス・メソッドに public または open を指定。
(2) iOSプラグインの準備
UnityプロジェクトのAssets直下のPluginsに、以下のファイルを配置します。
・Assets/Plugins/Sample.mm
#import <UnityFramework/UnityFramework-Swift.h>
#ifdef __cplusplus
extern "C" {
#endif
void Hello() {
[Sample hello];
}
#ifdef __cplusplus
}
#endif
iOSのプラグインは「Objective-C++」で記述します。extern "C" {} 内にメソッドを定義します。
「#import <UnityFramework/UnityFramework-Swift.h>」は、SwiftコードをXcodeでビルドした時に自動生成されるヘッダファイルです。これによって、[Sample hello] のようにSwiftコードにアクセスできます。
(3) Unityのコードの準備
Hierarchyウィンドウに空のゲームオブジェクトを作成し、以下のスクリプトを追加します。Scriptsフォルダに生成しています。(特別なフォルダ以外であればどこでもOK)
・Assets/Scripts/Sample.cs
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Runtime.InteropServices;
public class Sample : MonoBehaviour
{
[DllImport("__Internal")]
private static extern void Hello();
void Start()
{
Hello();
}
}
UnityのC#からiOSプラグインの関数を利用するには、DllImport と extern で関数のインポート宣言を行う必要があります。
(4) UInityプロジェクトをiOSにビルド。
Xcodeプロジェクトが出力されます。
(5) Xcodeプロジェクトを開き、Generalの「Bundle Identifier」と「Signing & Capabilities」を確認して実行。
成功するとアプリが起動し、Xcodeのデバッグ出力に文字列が表示されます。
Hello Swift!
3. 引数と戻り値
◎ プリミティブ型(int, float, bool等)
プリミティブ型(int, float bool等)は、変換なし利用できます。
// Unityの関数インポート
void SetNum(int num) {
[Sample setNumWithNum:num];
}
// Unity
SetNum(123);
↓
// iOSプラグイン
void SetNum(int num) {
[Sample setNumWithNum:num];
}
↓
// Swiftコード
@objc public static func setNum(num:Int) {
print(num)
}
// Unityの関数インポート
int GetNum() {
return (int)[Sample getNum];
}
// Unity
int num = GetNum();
↓
// iOSプラグイン
int GetNum() {
return (int)[Sample getNum];
}
↓
// Swiftコード
@objc public static func getNum() -> Int {
return 456;
}
◎ 文字列型
文字列は、Unityのstring型はiOSプラグインで「char*」型で渡されるため、変換が必要になります。
// Unityの関数インポート
[DllImport("__Internal")]
private static extern void SetStr(string str);
// Unity
SetStr("abc");
↓
// iOSプラグイン
void SetStr(const char *c) {
// char* → NSString
NSString *str = [NSString stringWithCString:c encoding:NSUTF8StringEncoding];
[Sample setStrWithStr:str];
}
↓
// Swiftコード
@objc public static func setStr(str:String) {
print(str)
}
// Unityの関数インポート
[DllImport("__Internal")]
private static extern string GetStr();
// Unity
string str = GetStr();
↓
// iOSプラグイン
char* GetStr() {
NSString* str = [Sample getStr];
// NSString → char*
const char *c = (char *)[str UTF8String];
char* retC = (char*)malloc(strlen(c) + 1);
strcpy(retC, c);
retC[strlen(c)] = '\0';
return retC;
}
↓
// Swiftコード
@objc public static func getStr() -> String {
return "def";
}
4. SwiftからUnityのメソッドを呼ぶ
SwiftからUnityのメソッドを呼ぶには、UnitySendMessage()を使います。「iOSプラグイン」内から呼ぶことが可能です。
UnitySendMessage(const char* obj, const char* method, const char* msg)
・ obj: ゲームオブジェクト名
・ method: メソッド名
・ msg: 引数として渡すパラメータ
「iOSプラグイン」から「Swiftコード」にコールバックを渡して、そのコールバックでSwiftはUnityにアクセスします。
// Unityの関数インポート
[DllImport("__Internal")]
private static extern void CallbackTest();
// Unity
CallbackTest();
↓
// iOSプラグイン
void CallbackTest() {
[Sample callbackTestOnCallback:^(NSString *str){
UnitySendMessage("Sample", "Test", (char *)[str UTF8String]);
}];
}
↓
// Swiftコード
static var onCallback: ((NSString) -> Void)!
@objc public static func callbackTest(onCallback: ((NSString)->Void)!) {
Sample.onCallback = onCallback
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
Sample.onCallback("Hello Unity!");
}
}
ゲームオブジェクト「Sample」のメソッド「Test」に文字列「Hello Unity!」をコールバックします。
public void Test(string str)
{
print(str+"\n");
}
5. 参考リンク
・ [Unity] C#とObjective-Cの連携まとめ
・ FrameworkでSwiftとObjective-C混ぜるのはやばい
この記事が気に入ったらサポートをしてみませんか?