随着技术的发展,越来越多的APP期望拥有3D,AR的能力。要达到这个目标可以选择使用原生开发,也可以使用Unity成熟的3D开发技术链,通过嵌入的方式将Unity容器嵌入到APP中。这里介绍的是通过嵌入Unity容器的方式来实现APP的3D,AR能力的。
 
Unity集成到iOS应用的本质是将Unity中所有用到的资源,模型,代码打包成一个framework动态库,然后嵌入到APP的内部。APP启动后加载Unity页面时,会加载这个framework动态库和里面的所有资源。然后在APP中展示这个Unity页面。
 
Unity集成到iOS应用的官方提供的方案是以Workspace的方式集成,具体步骤如下:
1.Unity项目通过Unity Editer 导出一个iOS项目,这个iOS项目里包含了整个Unity项目的所有代码和资源,可以直接运行在iOS系统上。
2.用Xcode创建一个原生的iOS项目
3.用Xcode创建一个Workspace, 然后通过add file 的形式将这2个项目添加到一个Workspace下面。
4.修改Unity-iPhone项目打包设置,使其打包出适合嵌入的UnityFramework动态库,
5.修改NativeiOSApp项目配置,添加UnityFramework动态库。
对Workspace下面的2个项目进行配置
Unity-iPhone创建
在生成UnityFramework动态库前,需要将Unity项目导出一个iOS项目,导出的过程如下:
1.点击File->Building Settings进入到选择导出页面

2.选择要导出的平台,这里选择iOS,然后点击右下角的"Switch Plateform"按钮,然后点击上面的“Add Open Scenes”添加场景

3.点击“Build”,导出iOS项目

Unity-iPhone设置
关闭以Workspace方式打开的Xcode,单独打开Unity-iPhone项目
1.在Unity-iPhone项目中,设置Data 这个Group的 Target Memebership, 将里面的UnitFramework项打勾,表示这个Data在生成Framework静态库时也要作为其中的一员,放置进去。
2.将NativeCallProxy.h头文件从Framework的 protect组移动到public组,将头文件开放出来。路径为: Unity-iPhone / Libraries / Plugins / iOS / NativeCallProxy.h
3.手机连接电脑,运行,生成静态库。
NativeiOSApp原生项目设置
以Workspace方式打开项目
1.在NativeiOSApp Target - General - Frameworks, Libraries, and Embedded Content 通过点击+ 将UnityFramework设置嵌入到项目中
2.在NativeiOSApp Target - Build Phases - Link Binary With Libraries中,点击-,将UnityFramework移除,表示禁止在项目链接时将UnityFramework链接到可执行文件中,它只作为内嵌在APP中的静态库在运行时加载使用。
3.手机连接电脑,运行,看到Demo运行的效果。
 
 
Unity与原生通信
Unity调用原生
1.首先在原生中实现代理协议NativeCallProxy中的方法(注册由谁来处理unity的调用)和添加暴露给unity的方法。
NativeCallProxy.h文件中方法的声明
__attribute__ ((visibility("default")))
@interface FrameworkLibAPI : NSObject
// call it any time after UnityFrameworkLoad to set object implementing NativeCallsProtocol methods
+(void) registerAPIforNativeCalls:(id<NativeCallsProtocol>) aApi; @end
NativeCallProxy.cpp文件中方法的实现
@implementation FrameworkLibAPI

id<NativeCallsProtocol> api = NULL;
+(void) registerAPIforNativeCalls:(id<NativeCallsProtocol>) aApi
{
api = aApi;
} @end
给Unity暴露的原生调用方法
extern "C" {
void showHostMainWindow(const char* color) { return [api showHostMainWindow:[NSString stringWithUTF8String:color]]; }
}
2.然后在原生的Unity启动时,注册这个处理的对象
- (void)initUnity
{
[self setUfw: UnityFrameworkLoad()];
// Set UnityFramework target for Unity-iPhone/Data folder to make Data part of a UnityFramework.framework and uncomment call to setDataBundleId
// ODR is not supported in this case, ( if you need embedded and ODR you need to copy data )
[[self ufw] setDataBundleId: "com.unity3d.framework"];
[[self ufw] registerFrameworkListener: self];
[NSClassFromString(@"FrameworkLibAPI") registerAPIforNativeCalls:self];
}
3.在Unity中,调用iOS的原生方法
Cube.cs脚本中声明在APP中存在方法showHostMainWindow
#if UNITY_IOS || UNITY_TVOS
public class NativeAPI {
[DllImport("__Internal")]
public static extern void showHostMainWindow(string lastStringColor);
}
#endif
Cube.cs脚本中添加Unity 2d按钮点击事件,调用iOS原生方法
void OnGUI()
{
GUIStyle style = new GUIStyle("button");
style.fontSize = 45;
if (GUI.Button(new Rect(10, 300, 600, 100), "Show Main With Color", style)) showHostMainWindow();
} void showHostMainWindow()
{
#if UNITY_ANDROID
try
{
AndroidJavaClass jc = new AndroidJavaClass("com.unity.mynativeapp.SharedClass");
jc.CallStatic("showMainActivity", lastStringColor);
} catch(Exception e)
{
appendToText("Exception during showHostMainWindow");
appendToText(e.Message);
}
#elif UNITY_IOS || UNITY_TVOS
NativeAPI.showHostMainWindow(lastStringColor);
#endif
}
原生调用Unity
点击原生发送消息按钮,发消息给Unity。
self.btnSendMsg = [UIButton buttonWithType: UIButtonTypeSystem];
[self.btnSendMsg setTitle: @"Send Msg" forState: UIControlStateNormal];
[self.btnSendMsg addTarget: self action: @selector(sendMsgToUnity) forControlEvents: UIControlEventPrimaryActionTriggered]; - (void)sendMsgToUnity
{
[[self ufw] sendMessageToGOWithName: "Cube" functionName: "ChangeColor" message: "yellow"];
} /*
goName: 场景中的游戏物体GameObject
name: 这个游戏物体挂载的脚本中的一个方法
msg: 参数
*/
- (void)sendMessageToGOWithName:(const char*)goName functionName:(const char*)name message:(const char*)msg
{
UnitySendMessage(goName, name, msg);
} void UnitySendMessage(const char* obj, const char* method, const char* msg);
Cube.cs脚本中的方法实现
string lastStringColor = "";
void ChangeColor(string newColor)
{
appendToText( "Changing Color to " + newColor ); lastStringColor = newColor; if (newColor == "red") GetComponent<Renderer>().material.color = Color.red;
else if (newColor == "blue") GetComponent<Renderer>().material.color = Color.blue;
else if (newColor == "yellow") GetComponent<Renderer>().material.color = Color.yellow;
else GetComponent<Renderer>().material.color = Color.black;
}
 
Unity热更新
在Unity项目中使用纯C#构建的渐渐不能适应移动端的需求,移动端通常通过添加热更新插件来实现热更新功能。这个过程起关键作用的是Lua和起对应的解释器。
lua是解释型语言,并不需要事先编译成块,而是运行时动态解释执行的。
这样LUA就和普通的游戏资源如图片,文本没有区别,因此可以在运行时直接从WEB服务器上下载到持久化目录并被其它LUA文件调用。
Lua热更新解决方案是通过一个Lua热更新插件(如ulua、slua、tolua、xlua等)来提供一个Lua的运行环境以及和C#进行交互。
所以lua热更新的流程可以简单理解为:将逻辑代码使用脚本实现,再将脚本转化为文本资源,最后以更新资源的形式来更新程序,以此来实现热更新。
注意:
在iOS应用内的Unity容器中,Untiy的C#资源和Lua资源都是在Unity容器内部进行加载的。如果Unity采用的Lua热更新,则需要原生侧在Lua脚本和资源下载完成后通知Unity进行加载展示。
Demo地址
NativeiOSApp项目地址:https://github.com/zhfei/uaal-example
将 Unity 集成到原生 iOS 应用程序中官方文档:https://docs.unity3d.com/cn/2020.2/Manual/UnityasaLibrary-iOS.html
 
 
 
 
 

在原生APP中集成Unity容器的更多相关文章

  1. iOS原生项目中集成React Native

    1.本文的前提条件是,电脑上已经安装了CocoaPods,React Native相关环境. 2.使用Xcode新建一个工程.EmbedRNMeituan [图1] 3.使用CocoaPods安装Re ...

  2. 怎么在我们的App中集成条码扫描功能?

    现在很多App都有条码扫描功能,有的手机比如某米在照相机中集成了条码扫描功能,但是还有一部分手机没有这样的集成,比如韩国某星,需要自己下载一个条码扫描App.今天我们就来看看怎么在自己的App中集成一 ...

  3. APICloud原生APP中ajax需要用api.ajax

    报错截屏: APICloud原生APP中ajax请求需要用api.ajax(api对象的ajax方法来替代),否则会将引起请求失败. APICloud api.ajax

  4. c#中的Unity容器

    DIP是依赖倒置原则:一种软件架构设计的原则(抽象概念).依赖于抽象不依赖于细节 IOC即为控制反转(Inversion of Control):传统开发,上端依赖(调用/指定)下端对象,会有依赖,把 ...

  5. 在APP中集成iAd Banner展示广告盈利

    如果你已经做了一款超牛X的APP.你也许还有一件是需要操心.APP够好了,怎么盈利呢?你可以对下载你的APP的用户收费.也可以完全的免费,然后在APP里放广告来实现盈利.现在来说,除非一款APP真的是 ...

  6. 在Android App中集成Google登录

    技术文章 来源:码农网 发布:2016-09-19 浏览:194 摘要:今天,几乎所有的web和移动app都自带谷歌和Facebook登录,这对app开发者和用户来说是一个非常有用的功能,因为几乎每个 ...

  7. 如何在WCF中集成unity

    第一种是代码方式: 点击打开链接http://blogs.microsoft.co.il/gadib/2010/11/30/wcf-and-unity-20/ 还有一种方式可以扩展成配置文件,有时间再 ...

  8. RN与现有的原生app集成

    https://facebook.github.io/react-native/docs/integration-with-existing-apps.html RN可以很好地支持往一个原生的app上 ...

  9. 转发-UI基础教程 – 原生App切图的那些事儿

    UI基础教程 – 原生App切图的那些事儿 转发:http://www.shejidaren.com/app-ui-cut-and-slice.html 移动APP切图是UI设计必须学会的一项技能,切 ...

  10. 原生App切图的那些事儿

    如何切图? 了解iphone界面的尺寸 最小的分辨率是320x480,我们把这个尺寸定为基准界面尺寸(baseline),基准尺寸所用的图标定为1倍图(1x). 在实际设计过程中,为了降低设计成本,一 ...

随机推荐

  1. java中this的内存原理以及成员变量和局部变量

    this的内存原理 1.this的作用: 区分局部变量和成员变量 eg: public class Student{ private int age; public void method(){ in ...

  2. Django4全栈进阶之路20 项目实战(在线报修):项目需求分析

    为了实现一个在线报修系统,您可以按照以下步骤进行: 创建Django项目和应用 使用Django的命令行工具创建一个Django项目,并在该项目中创建一个名为"RepairApp" ...

  3. JSPModel

    JSPModel what JSP开发模型就是JSP Model,是用JSP语言写的 why 为了更好地使用jsp技术开发 How JSPModel1 Why 因为在jsp开发中,包含了数据处理/业务 ...

  4. rt下降40%?程序并行优化六步法

    1 背景 性能优化是我们日常工作中很重要的一部分,主要有以下原因: 降低服务器和带宽等硬件成本:用更少的资源处理更多的请求 提高现实世界的运行效率:人机处理效率存在数量级的偏差,同样机器世界的效率提升 ...

  5. AcWing 1024. 装箱问题

    有一个箱子容量为 V,同时有 n 个物品,每个物品有一个体积(正整数). 要求 n 个物品中,任取若干个装入箱内,使箱子的剩余空间为最小. 输入格式 第一行是一个整数 V,表示箱子容量. 第二行是一个 ...

  6. Vue 路由router

    简单案例: App.vue是核心组件,其中的<router-link>相当于a标签,to相当于href,export是暴露函数,这样某组件才能被其他组件识别到 代码: <templa ...

  7. 自定义组件模拟v-model

    在项目中常常会遇到一个组件中引入好几个子组件的情况,而引入的子组件和子组件之间又需要有数据交互,如果使用父组件作为桥梁进行数据交互这个也是可以的,只是有些麻烦,so最理想的是子组件和子组件自己去交互, ...

  8. 【RS】多光谱波段和全色波段的区别

    <p><strong>1.全色波段(Panchromatic Band)</strong></p> 全色图像是单通道的(即单波段灰色影像),其中全色是指 ...

  9. 自然语言处理(NLP)

    "自然语言处理(Natural Language Processing, NLP)是计算机科学领域与人工智能领域中的一个重要方向.它研究能实现人与计算机之间用自然语言进行有效通信的各种理论和 ...

  10. VUE路由传参的实用方式

    本文讲解了VUE项目中路由之间的传值方式,涉及到的方法都是开发时常用的,希望对大家有多帮助. 1. 方式一:使用router-link标签 1.1 params 传参 首先定义好路由 const ro ...