2013-02-12 3 views
53

У меня очень маленькая библиотека Objective-C, созданная для iOS, и я хочу экспортировать ее в Unity. Я понимаю основной процесс написания обертки csharp, которая марширует все вызовы в родную библиотеку, но я совершенно не знаю, с чего начать. Может кто-нибудь, пожалуйста, объясните шаг за шагом, как создать единый пакет с моей библиотекой, чтобы я мог также распространять его на других разработчиков.Как построить Unity3d-плагин для iOS

Документация Unity3d довольно короткая и ничего не объясняет.

Спасибо.

+4

Я должен был сделать это недавно на работе. Документация Unity не очень полезна, и я не нашел никакой полезной информации в Интернете. Мне понадобится время, чтобы поэтапно объединиться, поэтому, если никто не ставит меня первым, я отвечу на этот вопрос позже сегодня. – ChrisH

+0

Возможно, [этот ответ] (http://answers.unity3d.com/questions/147755/native-alert-on-ios-plugin.html) с сайта Unity может вам помочь. См. Мои комментарии, чтобы получить ссылку через машину wayback в сообщение блога. – Kay

+0

http://stackoverflow.com/questions/8321939/how-to-use-an-xcode-game-on-unity3d/8333120#8333120 и http://stackoverflow.com/questions/4272413/mixing-unity-generated -код с объективом-c-in-ios/7076887 # 7076887 тоже может помочь – Kay

ответ

77

Хорошо, после нескольких дней работы с Unity3d на Mac я, наконец, понял это. Весь код в этом руководстве является фиктивным. Я написал этот материал за 15 минут или около того, так что не надо беспокоиться о ошибках и опечатках.

1) Open Unity, создать новый проект (File -> New Project) и сохраните его где-то

2) Когда проект создается он имеет следующую структуру:

  • ProjectName/Assets (это то, что вам нужно)
  • ProjectName/Library (Nevermind, что там)
  • 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, так что это wasn ' т трудно сделать обертку 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_PATH и PROJECT_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, чтобы получить сборку пакета.Все материалы из Assets будут включены в проект XCode для вашего проекта Unity при его создании через File -> Build Settings в Unity Editor. Вы можете использовать сгенерированный пакет для распространения кода другим разработчикам, чтобы они могли просто включить вашу библиотеку в свои проекты Unity, дважды щелкнув файл пакета.

Не забудьте выключить Unity Editor при запуске этого скрипта, иначе он может не построить пакет.

Если у вас есть какие-то проблемы и пакет не отображается, этот сценарий всегда печатает журнал на export.log

Следующие шаги имеют смысл, только если вы хотите сделать проект единства Demo для библиотеки (полезно для тестирования как минимум)

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, выберите ее и в нижней части панели «Инспектор» (правая боковая панель) нажмите «AddComponent», выберите «Сценарии -> сценарий MySDKDemo»

12) Создайте проект XCode и запустите на устройстве ,

Несколько нот

1) Плагины не работают в редакторе Unity, просто потому, что они не компилируется в режиме реального времени, ну, не знаю, но, вероятно, пока вы не используете C# в ваших плагинов, возможно, C# -файл связан с ним и работает в среде редактора.

2) Это сообщение не распространяется на маршалинг или управление данными/памятью между нативным < -> управляемым кодом, поскольку он очень хорошо документирован.

Interop with Native Libraries @ Mono project

3) Callbacks из C# для C может быть передано с помощью C# делегатов, на С-стороне вы используете стандартные функции декларации, на C# стороне вы объявляете делегат с той же подписью. Кажется, что логические значения, целые числа и строки (C: char *) безупречно сортируются (я не говорю о политике управления памятью и кто ответственен за выпуск политики памяти или возврата значений).

Однако он не будет работать на прошивке строит вне коробки из-за ограничения платформы, но C# -в-C обратных вызовы все еще могут быть реализованы с использованием MonoPInvokeCallbackAttribute, полезные ссылки на эту тему:

на самом деле в единстве 4 есть AOT.MonoPInvokeCallbackAttribute уже реализован, он ограничен статическими делегатов, которые могут быть переданы в неуправляемый код, но все же лучше, чем ничего.

4) Есть способ получить Unity RootViewController с использованием функции UnityGetGLViewController. Просто объявите эту функцию в вашем файле реализации, т. Е.:

extern UIViewController *UnityGetGLViewController(); 

И использовать UnityGetGLViewController() всякий раз, когда вам нужно, чтобы получить доступ к RootViewController.

5) В деталях гораздо больше волшебства и уродства, держите свои C-интерфейсы как можно проще, иначе маршаллинг может стать вашим кошмаром, а также иметь в виду, что управляемое неуправляемое, как правило, дорого.

6) Вы определенно используете некоторые фреймворки в своем родном коде, и вам не нужны проблемы с компоновщиками. Например, если вы используете Keychain в своей библиотеке, тогда вам нужно включить Security.framework в проект Xcode.

Я предлагаю попробовать XUPorter, он помогает Unity интегрировать любые дополнительные зависимости в проект Xcode.

Удачи вам!

+2

Удивительный пост. Благодаря! –

+0

Спасибо, ваш пример вызывает только функцию. Можете ли вы вернуть данные из Objective-C, используя тот же подход выше, передавая переменные по ссылке или возвращая объект функции? – Boon

+0

@Boon да, вы можете, но вам нужно будет следовать определенным правилам, чтобы убедиться, что данные соответствуют размерам и правильному переносу памяти. Этот процесс называется маршалингом, и в этой теме много статей, вам может показаться полезным прочитать «Interop with Native libraries» на веб-сайте проекта Mono. – Andy

4

Я написал сообщение о том, как создать плагин iOS для единства. Вы можете проверить его here. Надеюсь, поможет. Спасибо.

Смежные вопросы