Unity与andorid交互的那些坑(偏andorid)
Unity与andorid交互的那些坑
近期接触到需要Unity与andorid交互的项目,我负责andorid开发,记录一下开发过程遇到的坑,代码偏向于android端处理,unity端其他操作自行百度
一.unity工程师导出andorid项目
有两种方式,推荐用Gradle方式导出(unity同事工作),导出的工程结构如下
二.合并进主项目
上图红框中文件都可在导出的unity工程文件中找到,添加进合并的原生项目里,并在AndroidManifest.xml以中添加
<uses-feature android:glEsVersion="0x00020000" /><uses-feature android:name="android.hardware.vulkan" android:required="false" /><uses-feature android:name="android.hardware.touchscreen" android:required="false" /><uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" /><uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
<application ....>
<activity android:label="@string/app_name"android:hardwareAccelerated="true"android:launchMode="singleTask"android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection"android:name=".ui.activity.UnityPlayerActivity"><meta-data android:name="unityplayer.UnityActivity" android:value="true" /></activity>
</application>
build.gradle(app)中添加
implementation files('libs/unity-classes.jar')implementation(name: 'UniWebView', ext: 'aar')
启动Unity项目
//原生中调用
startActivity(Intent(this, UnityPlayerActivity.class));
三.数据交互
/*** andorid 端原生调用unity* */UnityPlayer.UnitySendMessage("Unity项目C中的类名", "类的方法名", "params");/*** unity调用的原生方法*/
C#中的代码
1.新建两个按钮
2.点击调用
按钮一:
AndroidJavaObject jc =
new AndroidJavaObject("com.xxx.xxx.connection.UnityMessage");
AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("Instance");
jo.Call ("showToast","我是Unity传来的消息");按钮二:
AndroidJavaObject jc =
new AndroidJavaClass ("com.xxx.xxx.ui.activity.UnityPlayerActivity");
AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
jo.Call ("showToast","我是Unity传来的消息");
以上是网上各处都会提到的方法,具体参数含义看看其他博客说明,此处只说明需要注意的点
1.'UnityMessage' 'UnityPlayerActivity' 需要已经实例化
2.'Instance' 'currentActivity' 需要在类中声明
3.'showToast' 方法无法直接实现 ,需要 handle / runOnUiThread 实现
UnityPlayerActivity.java中添加以下代码
public static UnityPlayerActivity currentActivity;@Overrideprotected void onCreate (Bundle savedInstanceState){....currentActivity = this;UnityMessage.getInstance();}public void showToast(String msg){ThreadUtils.runOnUiThread(new Runnable() {@Overridepublic void run() {ToastUtils.showLong(msg);//andorid 端调用unityUnityPlayer.UnitySendMessage("Main", "OnLogin", "Test Login"); //unity方法UnityPlayer.UnitySendMessage("Main", "TestSend", "TestSend"); //unity方法}});}
UnityMessage.java
import com.blankj.utilcode.util.ThreadUtils;
import com.blankj.utilcode.util.ToastUtils;/*** <pre>* Created by DengDongQi on 2020/4/23* </pre>*/
public class UnityMessage {private static UnityMessage Instance = null;private UnityMessage() {}public static UnityMessage getInstance() {if(Instance == null){synchronized (UnityMessage.class){if(Instance == null){Instance = new UnityMessage();}}}return Instance;}public void showToast(String msg){ThreadUtils.runOnUiThread(new Runnable() {@Overridepublic void run() {ToastUtils.showLong(msg);}});}
}
测试交互
点击按钮
至此双向交互完成
四.后记
测试完交互后发现,启动unity页面后,按系统返回键无法退回原生界面,只能在UnityPlayerActivity 中某处调用finish()方法结束页面
调用finish之后会出现整个进程也会随着页面结束而被杀掉,原因是UnityPlayerActivity 的 onDestroy()中调用了mUnityPlayer.quit(); quit中调用了this.kill();
为了退出unity界面而不结束进程,需要在AndroidManifest中UnityPlayerActivity的声明中添加android:process=":unity3d"
声明为子进程后双向交互有出现问题,之后需要使用跨进程交互方式才能在原生主进程中接收交互信息
五.跨进程数据交互
选用比较简单的Messenger方式实现:修改后具体代码
UnityMessage.java
/*** <pre>* Created by DengDongQi on 2020/4/23* Unity 直接发送数据至 UnityMessage 再由UnityMessage 传递进 HandleUnityMessengerService ,Service处理并返回结果** Unity项目为客户端 , 原生APP为服务端** 原生APP内 Unity进程为客户端 ,主进程为服务端** </pre>*/
public class UnityMessage {// 客户端请求码public static final int CLIENT_REQUEST_CODE = 0X1001;// 客户端请求字段public static final String CLIENT_REQUEST_MSG = "client_request";// 单例private static UnityMessage Instance = null;// 上下文private Context mContext;// 客户端handleprivate ClientHandler mhandle = new ClientHandler();// 客户端送信者private Messenger mMessenger = new Messenger(mhandle);// 服务端送信者private Messenger mServiceMessenger = null;// 服务连接对象private UnityMsgServiceConnection mServiceConnected;// 避免内存泄露 弱引用获取contextprivate static WeakReference<Context> weakReference;private static void initWeakReferenceContext(Context context) {weakReference = new WeakReference<>(context);}private Context getWeakReferenceContext() {return weakReference.get();}private UnityMessage() {}public static UnityMessage getInstance() {if (Instance == null) {synchronized (UnityMessage.class) {if (Instance == null) {Instance = new UnityMessage();}}}return Instance;}public void init(Context context){initWeakReferenceContext(context);this.mContext = getWeakReferenceContext();mServiceConnected = new UnityMsgServiceConnection();bindService();}public void sendMsgToAndroid(String msg) {ThreadUtils.runOnUiThread(new Runnable() {@Overridepublic void run() {sendMsgToService(msg);}});}public void showToast(String msg){ThreadUtils.runOnUiThread(new Runnable() {@Overridepublic void run() {LogUtils.d("unity进程收到信息:"+msg);sendMsgToService(msg);}});}/*** 发送消息到服务端* @param msg*/private void sendMsgToService(String msg) {Message message = mhandle.obtainMessage();message.what = CLIENT_REQUEST_CODE;Bundle bundle = new Bundle();bundle.putString(CLIENT_REQUEST_MSG, msg);message.setData(bundle);message.replyTo = mMessenger;if (mServiceMessenger != null) {try {LogUtils.d("发送至主进程:"+msg);mServiceMessenger.send(message);} catch (RemoteException e) {e.printStackTrace();}}}/*** 客户端handler* 处理服务端(主进程)返回的数据* */private class ClientHandler extends Handler {@Overridepublic void handleMessage(@NonNull Message msg) {super.handleMessage(msg);if (msg != null) {if (msg.what == HandleUnityMessengerService.SERVICE_RESULT_CODE) {// 服务端返回的数据String data = msg.getData().getString(HandleUnityMessengerService.SERVICE_RESULT_MSG);// 返回给unity项目if(data!=null) {LogUtils.e(data);UnityPlayer.UnitySendMessage("Main", "TestSend", data);}}}}}/*** 绑定服务*/private void bindService() {Intent intent = new Intent(mContext, HandleUnityMessengerService.class);mContext.bindService(intent, mServiceConnected, Service.BIND_AUTO_CREATE);}private class UnityMsgServiceConnection implements ServiceConnection {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {LogUtils.d("绑定-->" + name.getClassName());mServiceMessenger = new Messenger(service);}@Overridepublic void onServiceDisconnected(ComponentName name) {LogUtils.d("解绑-->" + name.getClassName());mServiceMessenger = null;}}/*** 释放资源* */public void release(){unbindService();if(mhandle!=null){mhandle.removeCallbacksAndMessages(null);}}/*** 解绑服务* */private void unbindService() {if (mServiceConnected != null && mContext != null) {mContext.unbindService(mServiceConnected);}}}
HandleUnityMessengerService.kt
/*** 服务端创建一个 Service 来处理客户端请求,同时通过一个 Handler 对象来实例化一个 Messenger 对象,* 然后在 Service 的 onBind 中返回这个 Messenger 对象底层的 Binder 即可。* */
class HandleUnityMessengerService : Service() {companion object{//服务端的返回码const val SERVICE_RESULT_CODE = 0X1002//服务端的返回数据字段const val SERVICE_RESULT_MSG = "service_result"}private class MessageHandler : Handler(){override fun handleMessage(msg: Message?) {super.handleMessage(msg)when(msg!!.what){UnityMessage.CLIENT_REQUEST_CODE -> {LogUtils.e("服务端收到客服端信息:${msg.data.getString(UnityMessage.CLIENT_REQUEST_MSG)}")val client = msg.replyToval replyMsg = Message()replyMsg.what = SERVICE_RESULT_CODEval bundle = Bundle()bundle.putString(SERVICE_RESULT_MSG,"客服端你好!服务端已经收到你的信息了!")replyMsg.data = bundleclient.send(replyMsg)}}}}private val messenger = Messenger(MessageHandler())override fun onBind(intent: Intent): IBinder {return messenger.binder}override fun onUnbind(intent: Intent?): Boolean {return super.onUnbind(intent)}override fun onDestroy() {super.onDestroy()}
}
UnityPlayerActivity中的onCreate() onDestroy()中
//Unity消息接收
UnityMessage.getInstance().init(this);
@Overrideprotected void onDestroy (){UnityMessage.getInstance().release();mUnityPlayer.quit();super.onDestroy();}
最后AndroidManifest添加
<serviceandroid:name=".connection.HandleUnityMessengerService"android:enabled="true"android:exported="true"/>
Unity与andorid交互的那些坑(偏andorid)相关推荐
- 开发手札:Unity与Android交互
先祝贺我国疫情基本结束,感谢为疫情奉献热血甚至生命的医护人员! 接下来进入正题. 用unity做一个手机app游戏基本上都需要与android和ios交互,比如调用系统函数,调用sdk等.这是unit ...
- 记Outlook插件与Web页面交互的各种坑 (含c# HttpWebRequest 连接https 的完美解决方法)
记Outlook插件与Web页面交互的各种坑 (含c# HttpWebRequest 连接https 的完美解决方法) 参考文章: (1)记Outlook插件与Web页面交互的各种坑 (含c# Htt ...
- Unity中纹理启用SRGB的坑
Unity中纹理启用SRGB的坑 __先说结论,在shader中不使用SRGB与Linear的转换函数的前提下,如果该纹理是Albedo.Emissive.Ramp或者其它颜色贴图,建议勾上SRGB, ...
- Unity和AndroidStudio交互制作SDK并和其他的SDK合并(微信APP支付)
本案例使用的AndroidStudio版本为 171.4408382 Unity版本为 5.2.4f1 如果跟我一样是新手,就请先看我下面这篇文章 https://blog.csdn.net/weix ...
- 2021-09-29 Unity WebGL平台开发遇到的坑
内容简介:最近在用Unity做一个 WebGL 平台的项目,开发过程中遇到了各种各样的坑,这里简单记录一下,以免以后再踩.首先是Http请求的问题,我最开始想的是,直接用C#里的写法,编辑器里测试毫无 ...
- Unity WebGL(一)Unity和JS交互
UNITY与JavaScript交互 前言 一.从 Unity 脚本调用 JavaScript 函数 1.在工程文件夹里新建"Plugins"文件夹,在内部创建一个.jslib扩展 ...
- Unity EvenTrigerer UI交互组件
Unity EvenTrigerer UI交互组件 Event Trigerer组件介绍 方便之处 事件选择 使用方法 1.拖拽法 代码添加 接口法 Event Trigerer组件介绍 该组件作用与 ...
- 关于Unity粒子系统碰撞的几个坑
关于Unity粒子系统碰撞的几个坑 最近公司的项目正好要用到粒子系统的碰撞,所以特意研究了一下.在实践中遇到了很多问题,所以借此文记录一下学习的过程.而且学习过程中发现网上这方面文章极少,所以也算借这 ...
- Unity XR实现交互(抓取、移动、旋转、传送、射击)-Pico
Unity XR 支持交互(抓取.移动.旋转.传送.射击) 文章目录 前言 Unity XR 提供了 XR 交互工具包,可以直接在包管理器中安装/更新.对于简单的交互需求unity 射线碰撞检测,可以 ...
最新文章
- 如何一小时杀入天池OCR比赛前排?
- Angular中数据循环ngFor、条件判断ngIf、ngSwitch、执行事件(click)、表单事件(keyup)、ngClass、ngStyle的使用
- C++ vector容器简单解释
- Android 应用 之路 百度地图API使用(3)
- Linux学习记录-文件、目录与磁盘
- DirectX - dds图片格式(DDSURFACEDESC2)
- Perl一行式:处理空白符号
- ffmpeg drawtext居中放置
- zxr10交换机配置手册vlan_最新中兴ZXR10交换机配置资料
- 树莓派 wiringpi 读取引脚_树莓派驱动的无人驾驶开发记录--驱动电机
- 51单片机——LED流水灯
- android开发者模式自动打开位置touch信息
- 基于JSoup的网络爬虫爬取小说内容
- Java OpenCV 图像处理34 图形图像 分水岭 watershed
- SWUST OJ 299: 平方和
- uniapp页面导出pdf
- mysql workbench安装教程_MySql可视化工具MySQL Workbench使用教程
- matlab谐波电流测量,基于MATLAB的谐波电流检测方法的建模与仿真
- painter qt 好恶心_Qt之有关于Painter的理解
- Easy_language