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)创建一个shell脚本来打包这些东西.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 编辑器中的 File -> Build Settings 生成资源时,Assets 中的所有内容都将包含在 Unity 项目的 XCode 项目中。您可以使用生成的包将您的代码分发给其他开发人员,这样他们就可以通过双击包文件将您的库简单地包含到他们的 Unity 项目中。

运行此脚本时不要忘记关闭 Unity Editor,否则可能无法构建包。

如果你有一些问题并且包没有出现,这个脚本总是将日志打印到 export.log

仅当您想为您的库制作一个演示统一项目时,接下来的步骤才有意义(至少有利于测试)

9) 您可以将创建的 Unity 项目 (ProjectName.unity) 放入其中,Assets/MySDKDemo以便在您的包中进行演示。

10) 为您的 Demo 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 Editor 的左侧边栏中找到“Main Camera”,选择它并在 Inspector 面板(右侧边栏)的底部单击 AddComponent,选择 Scripts -> MySDKDemo script

12) 构建 XCode 项目并在设备上运行。

几条笔记

1)插件不能在 Unity 编辑器中工作,仅仅是因为它们不是实时编译的,嗯,不确定但可能直到你在插件中使用 C# 之前,C# 的东西可能会立即链接并在编辑器环境中工作。

2) 这篇文章不涉及本机 <-> 托管代码之间的封送处理或数据/内存管理,因为它有很好的文档记录。

与本机库互操作 @ Mono 项目

3) 可以使用 C# 委托传递从 C# 到 C 的回调,在 C 端使用标准函数声明,在 C# 端声明具有相同签名的委托。布尔值、整数和字符串(C:char*)似乎被完美地编组(我不谈论内存管理策略以及谁负责释放内存或返回值策略)。

但是,由于平台限制,它不适用于开箱即用的 iOS 构建,但 C#-to-C 回调仍然可以使用 MonoPInvokeCallbackAttribute 实现,有关此主题的有用链接:

实际上在 Unity 4 中AOT.MonoPInvokeCallbackAttribute已经实现了,它仅限于可以传递给非托管代码的静态委托,但总比没有好。

4) 有一种使用UnityGetGLViewController函数获取 Unity RootViewController 的方法。只需在您的实现文件中声明此函数,即:

extern UIViewController *UnityGetGLViewController();

UnityGetGLViewController()在您需要访问 RootViewController 时使用。

5) 细节中有更多神奇和丑陋的东西,让你的 C 接口尽可能简单,否则编组可能会成为你的噩梦,还要记住,托管到非托管通常很昂贵。

6)您肯定在本机代码中使用了一些框架,并且您不希望出现链接器问题。例如,如果您在库中使用 Keychain,则需要将 Security.framework 包含到 Xcode 项目中。

我建议尝试一下XUPorter,它可以帮助 Unity 将任何额外的依赖项集成到 Xcode 项目中。

祝你好运!

于 2013-02-14T22:13:27.923 回答