見出し画像

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コードを呼び出すことができます。

画像3

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混ぜるのはやばい



この記事が気に入ったらサポートをしてみませんか?