Unity- 实现 Building Plugins for iOS(含Demo)

这段时间,由于项目需求,需要实现Unity和iOS之间的代码交互(如,在Unity中使用iOS原生UI,二者之间方法互调等),故做了相关的技术预研及演示Demo。下文简单记录了本次实现,仅供参考。由于本人也是初学Unity,又不足之处望高手指正。

在Unity中使用iOS原生代码,其实唯一的方法就是通过插件的方式,官方文档 Building Plugins for iOS 其实已经对此做了较详细的阐述(当然也有对应的  Building Plugins for Android   和 Building Plugins for Desktop Platforms  )。我想实现的需求,能够在Unity导出生成的Xcode项目运行后,屏幕下方使用iOS原生UI--ToolBar,左右各有原生Item进行方法的交互。

Unity中调用Objective-C/C++方法

1、[DllImport("__Internal")] 特性

在Unity新建项目中,Progect --> Create --> C# Script ,然后使用 [DllImport("__Internal")] 特性来标识用Objective-C/C++实现的函数。如下:

[DllImport ("__Internal")]
private static extern void ActivateUI_iOS();

而在脚本中,我选择在void Start () 调用该方法:

void Start () {
	if (Application.platform == RuntimePlatform.IPhonePlayer) {
		ActivateUI_iOS();
	}
}

脚本写好后,添加引用:using System.Runtime.InteropServices ,然后绑定到目标对象(本Demo绑定到 Main Camera,同时创建了球和文本对象作为Unity的显示)。

2、extern"C" 

在对应的iOS项目文件 .mm 中对应的用 extern"C"  来标识接口,以及 void ActivateUI_iOS()方法的实现:

extern "C" {
    void ActivateUI_iOS() {
        //Get the applications UIWindow
        UIWindow *window = [[UIApplication sharedApplication] keyWindow];
        //Create the RootViewController from a XIB file.
        ViewController *rootViewController = [ViewController sharedManager];
        rootViewController.view.frame = window.bounds;
        rootViewController.view.frame = CGRectMake(0, window.bounds.size.height - 44, 320, 44);
        //Add the RootViewController view to the main window.
        [window addSubview: rootViewController.view];
    }
}

因为 extern "C" 是C++语法,故应将.m文件改为.mm,编译才能通过。而 ViewController.h/m/xib 实现的就是界面展示的功能(View背景色为透明,才能显示Unity所展示的):

Unity- 实现 Building Plugins for iOS(含Demo)_第1张图片  Unity- 实现 Building Plugins for iOS(含Demo)_第2张图片

3、文件导入Unity项目中,生成Xcode工程,编译运行

Xcode运行项目没问题后,将原生代码(.a,.m,.mm,.c,.cpp文件)选中,拖入 Unity --> Project --> Plugins --> iOS 中(不能再有子目录),然后 File --> Build Settings 生成Xcode 工程编译运行。你会发现新版Unity已经自动合并这些文件到Xcode工程的Libraries目录下。而.h文件不会被包括在Xcode项目树之中,但是他们会在最终产生的文件系统中出现,这样能支持.m/.mm/.c/.cpp的编译。注:必须真机运行。效果如下(右图为点击 ShowAlert 后弹出 AlertView):

Unity- 实现 Building Plugins for iOS(含Demo)_第3张图片     Unity- 实现 Building Plugins for iOS(含Demo)_第4张图片

若运行后没有展示下面的 ToolBar,请修改生成工程中 UnityAppController.mm -->- (void)showGameUI:(UIWindow*)window 方法。

iOS原生代码调用Unity的脚本代码

上文已实现了Unity脚本调用iOS原生代码,下面来实现在iOS原生代码中如何调用Unity脚本方法。

1、UnitySendMessage

Unity iOS版支持利用UnitySendMessage进行简单的本地管理回调功能:

UnitySendMessage("GameObjectName1","MethodName1", "Message to send");

这个方法包含三个参数:目标游戏对象的名称,调用的脚本方法,传递给脚本方法的信息字符串。

所以,在Demo中,实现点击 ToolBar 右边的 ChangeText 来改变 Unity中GUIText 对象的显示(由 Hello World 变为 Building Plugins for iOS)。在ViewController.m文件中加入ChangeText 点击事件:

-(IBAction)clickItem2:(id)sender
{
    UnitySendMessage("Main Camera", [@"changeLabelShow" UTF8String], [@"Building Plugins for iOS" UTF8String]);
}
对应的Unity脚本中,实现changeLabelShow 这个方法:

public void changeLabelShow(string textStr){
	textObject.text = textStr;
}
记住先要声明和关联这个textObject:

public GUIText textObject;

最后,按照 3 中步骤,真机编译运行,点击右边Item后效果如下:

Unity- 实现 Building Plugins for iOS(含Demo)_第5张图片

注:

1、只有符合以下结构的脚本方法才能被从本地方法调用:

            function MethoName(message:string)

2、调用UnitySendMessage是异步的,会有1帧的延迟。

总结

1、在Unity中通过插件的方式实现调用iOS原生代码。

2、 在Unity中使用原生UI,但是比起在Unity中直接绘制UI,原生UI效率要更低。因为在Unity中绘制UI时, Unity可以尽可能的优化, 用尽量少的draw call去绘制UI, 而NativeUI并不受控制。

3、编译运行是个麻烦的过程, 从Unity生成一个XCode工程, 然后到XCode编译完成, 再到载入真机的过程是相当的漫长。机子性能不行的,额。。。自己感受吧。




你可能感兴趣的:(Unity)