ios - 如何为 iOS 构建 Unity3d 插件

标签 ios objective-c unity3d

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

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

谢谢。

最佳答案

好吧,在 Mac 上用 Unity3d 玩了几天后,我终于弄明白了。本指南中的所有代码都是虚拟的。我在 15 分钟左右写了这些东西,所以不要被错误和错别字所困扰。

1)打开Unity,创建新项目(File -> New Project)并将其保存在某处

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 对象都是以单例形式实现的,所以它不是'很难制作一个 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

    仅当您想为您的库制作 Demo 统一项目(至少适合测试)时,后续步骤才有意义

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

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

    几条笔记

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

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

    Interop with Native Libraries @ Mono project

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

    然而,由于平台限制,它不能在开箱即用的 iOS 构建上运行,但 C# 到 C 的回调仍然可以使用 MonoPInvokeCallbackAttribute 来实现,有关此主题的有用链接:
  • Reverse Callbacks @ Xamarin Docs
  • MonoPInvokeCallbackAttribute example @ Xamarin Forums

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

    4) 有一种方法可以使用 UnityGetGLViewController 获得 Unity RootViewController功能。只需在您的实现文件中声明此函数,即:
    extern UIViewController *UnityGetGLViewController();
    

    并使用 UnityGetGLViewController()每当您需要访问 RootViewController 时。

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

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

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

    祝你好运!

    关于ios - 如何为 iOS 构建 Unity3d 插件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14834626/

    相关文章:

    ios - 如何防止 UITabBar 展开转场?

    c# - 如何避免错误登录时锁定 UI?

    unity3d - Unity 的良好命名约定是什么?

    javascript - 如何识别 FlipBoard 或 MobileRss 中的自定义 UIWebView

    c# - 来自 PhotoCaptureFrame 的 IMFMediaBuffer

    ios - NSURLAuthenticationChallenge.sender 返回 nil

    c++ - 使用C++ 17构建ios应用程序?

    ios - ALAsset 图像为空

    ios - NSUserDefaults boolean 逻辑

    ios - 子类化 PFUser。访问当前用户