我有一个非常小的Objective-C库,用于iOS,我想将其导出到Unity。我了解编写csharp包装器的基本过程,它会调用所有本地库,但我完全不知道从何开始。请问是否可以逐步说明如何创建带有我的库的Unity软件包,以便我也可以将其分发给其他开发人员。
Unity3d文档非常简要,没有解释任何内容。
谢谢。
我有一个非常小的Objective-C库,用于iOS,我想将其导出到Unity。我了解编写csharp包装器的基本过程,它会调用所有本地库,但我完全不知道从何开始。请问是否可以逐步说明如何创建带有我的库的Unity软件包,以便我也可以将其分发给其他开发人员。
Unity3d文档非常简要,没有解释任何内容。
谢谢。
好的,在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代码中包装你的Objective-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_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 脚本以获取软件包构建。在 Unity 编辑器中通过文件 -> 构建设置生成时,Assets 中的所有内容都将包含在您的 Unity 项目中。您可以使用生成的软件包将代码分发给其他开发人员,他们只需双击软件包文件即可将您的库简单地包含到他们的 Unity 项目中。
不要忘记在运行此脚本时关闭 Unity 编辑器,否则可能无法构建软件包。
如果您遇到一些问题并且软件包未显示,则此脚本始终会将日志打印到 export.log
接下来的步骤仅在您想为您的库创建演示 Unity 项目时才有意义(至少用于测试)
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编辑器。在左侧边栏中找到“Main Camera”,选择它,在检查器面板的底部(右侧边栏)上点击AddComponent,选择Scripts-> MySDKDemo脚本。
12) 构建XCode项目并在设备上运行。
注意事项
1)插件在Unity编辑器中不起作用,因为它们没有实时编译,不确定,但可能只有在插件中使用C#时,C#内容立即链接并在编辑器环境中工作。
2)此帖子未涵盖与本机代码<->托管代码之间的数据/内存管理或处理方式,因为已经有很好的文档记录了这些内容。
3)从C#回调到C可以使用C#委托传递,您在C端使用标准函数声明,在C#端声明具有相同签名的委托。布尔值、整数和字符串(C:char*)似乎都能够无缝地进行封送(我不谈论内存管理政策以及谁负责释放内存或返回值政策)。
但是,由于平台限制,这在iOS构建中不会立即生效,但仍然可以使用MonoPInvokeCallbackAttribute实现C#-to-C回调。有关此主题的有用链接:
实际上,在Unity 4中已经实现了AOT.MonoPInvokeCallbackAttribute
,它仅限于可以传递到非托管代码的静态委托,但仍然比没有好。
4)有一种方法可以使用UnityGetGLViewController
函数获取Unity RootViewController。只需在您的实现文件中声明此函数,例如:
extern UIViewController *UnityGetGLViewController();
每当需要访问RootViewController时,请使用UnityGetGLViewController()
。
5) 在细节中有更多的魔法和丑陋的东西,尽可能保持C接口简单,否则封送可能会成为你的噩梦,并且要记住托管到非托管通常是昂贵的。
6) 您在本地代码中肯定使用了一些框架,而您不希望出现链接器问题。例如,如果您在库中使用Keychain,则需要将Security.framework包含在Xcode项目中。
我建议尝试一下 XUPorter ,它可以帮助Unity将任何其他依赖项���成到Xcode项目中。
祝好运!
Unity.exe
在里面。 - pronebird