68

iOS 用に構築された非常に小さな Objective-C ライブラリがあり、それを Unity にエクスポートしたいと考えています。すべての呼び出しをネイティブ ライブラリにマーシャリングする csharp ラッパーを作成する基本的なプロセスは理解していますが、どこから始めればよいかまったくわかりません。他の開発者にも配布できるように、ライブラリを使用してユニティ パッケージを作成する方法を段階的に説明してください。

Unity3d のドキュメントは非常に簡潔で、何も説明していません。

ありがとう。

4

1 に答える 1

89

さて、Mac で Unity3d を数日間プレイした後、ようやく理解できました。このガイドのコードはすべてダミーです。この記事は 15 分ほどで書いたので、間違いやタイプミスに悩まされないでください。

1) Unity を開き、新しいプロジェクトを作成し (ファイル -> 新しいプロジェクト)、どこかに保存します。

2) プロジェクトが生成されると、次の構造になります。

  • ProjectName/Assets(それがあなたが必要とするものです)
  • ProjectName/Library(そこに何があるか気にしないで)
  • ProjectName/ProjectSettings(あなたはそれを気にしません)
  • ProjectName/ProjectName.sln(MonoDevelop プロジェクト)

3)ProjectName/Assets次のフォルダーに移動して作成します: Plugins/iOS、最終的には次のようなフォルダー構造になります。ProjectName/Assets/Plugins/iOS

4) コンパイル済みのライブラリ (.a) ファイルと必要なヘッダーをライブラリの内部に配置するProjectName/Assets/Plugins/iOSか、そこにライブラリのソース コードをコピーします (.mm、.h、.m など..)。通常、C# からは C 関数にしかアクセスできないため、Objective-C のものを何らかの方法で C コードにラップする必要があります。私の場合、すべての Objective-C オブジェクトは Singleton の形式で実装されていたので、たとえば、C スタイルのラッパーを作成するのは難しいです。

CWrapper.h :

extern "C" void MySDKFooBarCFunction();

CWrapper.mm

#import "CWrapper.h"
#import "MyObjectiveCLibrary.h" // your actual iOS library header

void MySDKFooBarCFunction() {
    [MyObjectiveCLibrary doSomeStuff];
}

5) 次にProjectName/Assets、CSharp ラッパー クラスのフォルダーに移動して作成し、任意の名前を付けます。次に例を示します。ProjectName/Assets/MySDK

6) MySDK フォルダー内に MySDK.cs ファイルを作成します。C# ラッパーのダミーの例は次のようになります。

using UnityEngine;
using System;
using System.Runtime.InteropServices;

public class MySDK
{
    // import a single C-function from our plugin
    [DllImport ("__Internal")]
    private static extern void MySDKFooBarCFunction();

    // wrap imported C-function to C# method
    public static void FooBarCFunction() {
        // it won't work in Editor, so don't run it there
        if(Application.platform != RuntimePlatform.OSXEditor) {
            MySDKFooBarCFunction();
        }
    }
}

7) この内容をパッケージ化するシェル スクリプトを作成.unitypackageし、プロジェクト フォルダーの横 (内部ではありません) に配置します。必要に応じてスクリプト内の変数を調整EXPORT_PATHPROJECT_PATHます。

#!/bin/sh

WORKDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
UNITY_BIN="/Applications/Unity/Unity.app/Contents/MacOS/Unity"
EXPORT_PATH="${WORKDIR}/ProjectName.unitypackage"
PROJECT_PATH="${WORKDIR}/ProjectName"
ASSETS_PATH="Assets"

$UNITY_BIN -batchmode -quit \
-logFile export.log \
-projectPath $PROJECT_PATH \
-exportPackage $ASSETS_PATH $EXPORT_PATH

8) 作成した bash スクリプトを実行して、パッケージのビルドを取得します。Unity エディターの [ファイル] -> [ビルド設定] で生成すると、アセットのすべての要素が Unity プロジェクトの XCode プロジェクトに含まれます。生成されたパッケージを使用してコードを他の開発者に配布できるため、パッケージ ファイルをダブルクリックするだけでライブラリを Unity プロジェクトに簡単に含めることができます。

このスクリプトを実行するときは、Unity エディターをシャットダウンすることを忘れないでください。そうしないと、パッケージのビルドに失敗する可能性があります。

いくつかの問題があり、パッケージが表示されない場合、このスクリプトは常にログを export.log に出力します。

次のステップは、ライブラリの Demo unity プロジェクトを作成する場合にのみ意味があります (少なくともテストには適しています)。

9) 作成した Unity プロジェクト (ProjectName.unity) をAssets/MySDKDemo配置して、パッケージ内にデモを含めることができます。

10) でデモ Unity3d シーン用の簡単なスクリプトを作成します。Assets/MySDKDemo/MySDKDemo.cs例:

using UnityEngine;
using System;
using System.Collections;

public class MySDKDemo : MonoBehaviour
{   
    private GUIStyle labelStyle = new GUIStyle();
    private float centerX = Screen.width / 2;

    // Use this for initialization
    void Start ()
    {   
        labelStyle.fontSize = 24;
        labelStyle.normal.textColor = Color.black;
        labelStyle.alignment = TextAnchor.MiddleCenter;
    }

    void OnGUI ()
    {
        GUI.Label(new Rect(centerX - 200, 20, 400, 35), "MySDK Demo", labelStyle);
        if (GUI.Button(new Rect(centerX - 75, 80, 150, 35), "DoStuff"))
        {
            MySDK.FooBarCFunction();
        }
    }

}

11) Unity エディターに移動します。Unity エディターの左側のサイドバーで「Main Camera」を見つけて選択し、インスペクター パネル (右側のサイドバー) の下部で AddComponent をクリックし、Scripts -> MySDKDemo script を選択します。

12) XCode プロジェクトをビルドし、デバイスで実行します。

いくつかのメモ

1) プラグインは Unity エディターで機能しません。単にリアルタイムでコンパイルされていないためです。確かではありませんが、プラグインで C# を使用するまでは、おそらく C# のものはすぐにリンクされ、エディター環境で動作します。

2) この投稿では、マーシャリング、またはネイティブ <-> マネージ コード間のデータ/メモリ管理については、十分に文書化されているため、取り上げません。

ネイティブ ライブラリ @ Mono プロジェクトとの相互運用

3) C# から C へのコールバックは、C# デリゲートを使用して渡すことができます。C 側では標準関数宣言を使用し、C# 側では同じシグネチャでデリゲートを宣言します。ブール値、整数、および文字列 (C: char*) は問題なくマーシャリングされているようです (メモリ管理ポリシーや、メモリの解放や値ポリシーの戻りの責任者については触れません)。

ただし、プラットフォームの制限により、すぐに使える iOS ビルドでは機能しませんが、C# から C へのコールバックは、MonoPInvokeCallbackAttribute を使用して実装できます。このトピックに関する便利なリンク:

実際、Unity 4AOT.MonoPInvokeCallbackAttributeでは既に実装されており、アンマネージ コードに渡すことができる静的デリゲートに限定されていますが、何もないよりはましです。

4) 関数を使用して Unity RootViewController を取得する方法がありUnityGetGLViewControllerます。この関数を実装ファイルで宣言するだけです。

extern UIViewController *UnityGetGLViewController();

またUnityGetGLViewController()、RootViewController へのアクセスが必要な場合はいつでも使用してください。

5) 詳細にはもっと魔法と醜いものがあります。C インターフェイスをできるだけシンプルに保ちます。そうしないと、マーシャリングが悪夢になる可能性があります。また、マネージからアンマネージへの移行は一般的にコストがかかることに注意してください。

6) ネイティブ コードでいくつかのフレームワークを確実に使用しており、リンカーの問題は望ましくありません。たとえば、ライブラリで Keychain を使用する場合、Security.framework を Xcode プロジェクトに含める必要があります。

XUPorterを試してみることをお勧めします。これは、Unity が追加の依存関係を Xcode プロジェクトに統合するのに役立ちます。

幸運を!

于 2013-02-14T22:13:27.923 に答える