首页 文章

如何为iOS构建Unity3d插件

提问于
浏览
60

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

Unity3d文档非常简短,并没有解释任何内容 .

谢谢 .

2 回答

  • 5

    好吧,在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函数,所以你很难做出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 Editor中的文件 - >构建设置生成它时,来自Assets的所有内容都将包含在Unity项目的XCode项目中 . 您可以使用生成的包将代码分发给其他开发人员,这样他们只需双击包文件就可以将您的库包含到他们的Unity项目中 .

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

    如果您遇到一些问题且程序包未显示,则此脚本始终将日志打印到export.log

    Next steps make sense only if you want to make a Demo unity project for your library (good for testing at least)

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

    10)在 Assets/MySDKDemo/MySDKDemo.cs 为您的Demo 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 - > MySDKDemo script

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

    Few notes

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

    2)这篇文章不包括编组或本地< - >托管代码之间的数据/内存管理,因为它有很好的文档记录 .

    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项目中 .

    祝好运!

  • 82

    我写了一篇关于如何为统一创建iOS插件的文章 . 你可以查一下here . 希望能帮助到你 . 谢谢 .

相关问题