我有一个为iOS构建的非常小的Objective-C库,我想将其导出到Unity.我了解编写csharp包装器的基本过程,该包装器将所有调用封送到本机库,但我完全不知道从哪里开始.有谁能一步一步地解释一下如何用我的库创建一个unity包,这样我就可以把它分发给其他开发者了.
Unity3d文档非常简短,没有任何解释.
谢谢
我有一个为iOS构建的非常小的Objective-C库,我想将其导出到Unity.我了解编写csharp包装器的基本过程,该包装器将所有调用封送到本机库,但我完全不知道从哪里开始.有谁能一步一步地解释一下如何用我的库创建一个unity包,这样我就可以把它分发给其他开发者了.
Unity3d文档非常简短,没有任何解释.
谢谢
好吧,在Mac上玩了几天Unity3d之后,我终于明白了.本指南中的所有代码都是假的.我写了15分钟的错字,所以不必担心.
1) Open Unity, create new project (File -> New Project) and save it somewhere
2) 生成项目时,其 struct 如下:
ProjectName/Assets
(这就是你需要的)ProjectName/Library
(不管有什么)ProjectName/ProjectSettings
(你不在乎)ProjectName/ProjectName.sln
(单一开发项目)3) 转到ProjectName/Assets
并创建以下文件夹:Plugins/iOS
,这样最后你就有了这样的文件夹 struct :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 file,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_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) Run the created bash script to get your package build. All stuff from Assets will be included in XCode project for your Unity Project when you generate it via File -> Build Settings in Unity Editor. You can use generated package to distribute your code to other developers so they can simply include your library to their Unity projects by double clicking on the package file.
Don't forget to shutdown Unity Editor when you run this script, otherwise it may fail to build a package.
If you have some issues and package does not show up, this script always prints log to 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) 为你的演示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) Go to Unity Editor. Find the "Main Camera" in left sidebar in Unity Editor, select it and in the bottom of Inspector panel (right sidebar) click on AddComponent, select Scripts -> MySDKDemo script
12) 构建XCode项目并在设备上运行.
Few notes
1) 插件在Unity Editor中不起作用,仅仅是因为它们不是实时编译的,嗯,不确定,但在插件中使用C#之前,很可能C#stuff会立即链接并在编辑器环境中工作.
2) This post does not cover marshaling, or data/memory management between native <-> managed code, as it is very well documented.
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) 您肯定在本机代码中使用了一些框架,并且不希望出现链接器问题.例如,如果您在库中使用密钥链,则需要包含安全性.将框架转换为Xcode项目.
我建议try 一下XUPorter,它有助于Unity将任何额外的依赖项集成到Xcode项目中.
祝你好运