如何为iOS构建Unity3d插件

时间:2013-02-12 14:18:06

标签: ios objective-c unity3d

我有一个为iOS构建的非常小的Objective-C库,我想将它导出到Unity。我理解编写一个csharp包装器的基本过程,它将所有调用编组到本机库,但我完全不知道从哪里开始。任何人都可以逐步解释如何使用我的库创建一个统一包,这样我也可以将它分发给其他开发人员。

Unity3d文档非常简短,没有任何解释。

感谢。

2 个答案:

答案 0 :(得分:82)

好的,在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#wrapper的虚拟示例如下所示:

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脚本以获取包构建。当您通过File - &gt;生成它时,来自Assets的所有内容都将包含在Unity项目的XCode项目中。 Unity Editor中的构建设置。您可以使用生成的包将代码分发给其他开发人员,这样他们只需双击包文件就可以将您的库包含到他们的Unity项目中。

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

如果您遇到一些问题并且软件包没有显示,则此脚本始终将日志打印到export.log

只有当你想为你的图书馆制作Demo unity项目时才有意义(至少适合测试)

9)您可以将创建的Unity项目(ProjectName.unity)放到Assets/MySDKDemo,这样您就可以在包内部进行演示。

10)在Assets/MySDKDemo/MySDKDemo.cs为您的演示Unity3d场景创建一个简单的脚本,例如:

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。在Unity Editor的左侧边栏中找到“Main Camera”,选择它,然后在Inspector面板(右侧边栏)的底部单击AddComponent,选择Scripts - &gt; MySDKDemo脚本

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

几点注释

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

2)这篇文章不包括编组,或本地&lt; - &gt;之间的数据/内存管理。托管代码,因为它有很好的文档。

Interop with Native Libraries @ Mono project

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

然而,由于平台限制,它无法在iOS版本开箱即用,但C#-to-C回调仍然可以使用MonoPInvokeCallbackAttribute实现,这个主题的有用链接:

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

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

extern UIViewController *UnityGetGLViewController();

只要您需要访问RootViewController,就可以使用UnityGetGLViewController()

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

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

我建议尝试XUPorter,它可以帮助Unity将任何其他依赖项集成到Xcode项目中。

祝你好运!

答案 1 :(得分:5)

我写了一篇关于如何为统一创建iOS插件的帖子。你可以查看它here。希望能帮助到你。 感谢。