Unity 与Android 交互梳理

在这里插入图片描述

1.Unity 代码结构

由研发部门导出 Android Studio IDE可以识别的 Unity Module,手动进行依赖。代码结构同正常的Android Module 结构一致。

 Unity module -
      -build
      -libs
      -src
       -main
        -assets
        -java
        -jni
        -res
         AndroidManifest.xml
 build.gradle
 Gradle.properties
 Local.properties
2.Unity通信

项目中Unity 与Android由两种方式进行交互
方式一:unity 调用Android代码
在主Activity中声明与unity端协调好的方法及接收参数的类型
Public void toAppXXX( 参数类型 参数名)
方式二:Android 调用unity代码,底层实现方式由unity-class.jar 这个jar包进行封装。
UnitySendMessage(“GuiCamera”,“UserDataForUnity”,parameter);

Tip:
Unity 与 android 通信的原则,需要双方通信之前开启与unity的链接,onResume(),退出当前界面同时及时停止通信onPause( )

3.Unity初始化及资源解压

首先创建UnityPlayer,该对象继承Framlayout,需要将该对象添加到ViewTree中进行渲染

FrameLayout unityFrameLayout = getView(R.id.unity);
UnityPlayer mUnityPlayer = new UnityPlayer(this);
unityFrameLayout.addView(mUnityPlayer)

将mUnityPlayer的生命周期与Activity进行绑定
主要关注

  • mUnityPlayer.resume(); //开启通信
  • mUnityPlayer.pause(); //暂停通信

资源解压分为obb(海外),非obb。

  • 包含obb的海外版本,需要加载obb之后解压
  • 非obb的国内版,在初始化mUnityplayer之后,展示第一个场景自动解压资源。
4.快速编写具有通信能力的类

4.1 新建空白Activity,取名DemoActivity,并且在DemoActivity布局文件中添加一个Framlayout,作为mUnityPlay的容器。

 <FrameLayout
        android:id="@+id/unity"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" />

4.2 在DemoActivity的onCreate()或者OnResume()生命周期中进行初始化。初始化方式:

Void onCreate(){
UnityPlayer  mUnityPlayer = UnityPlayViewManager.getUnityPlay();
  unityGameFrameLayout.addView(mUnityPlayer);
}

Tip:UnityPlayViewManager 是一个单例,存储管理全局唯一的UnityPlayer对象

4.3 . 完成通信能力关键,将UnityPlayer 的生命周期与Activity的生命周期进行绑定,通过下面模板代码进行绑定。

@Override protected void onNewIntent(Intent intent)
    {
        // To support deep linking, we need to make sure that the client can get access to
        // the last sent intent. The clients access this through a JNI api that allows them
        // to get the intent set on launch. To update that after launch we have to manually
        // replace the intent with the one caught here.
        setIntent(intent);
    }

    // Quit Unity
    @Override protected void onDestroy ()
    {
        mUnityPlayer.destroy();
        super.onDestroy();
    }

    // Pause Unity
    @Override protected void onPause()
    {
        super.onPause();
        mUnityPlayer.pause();
    }

    // Resume Unity
    @Override protected void onResume()
    {
        super.onResume();
        mUnityPlayer.resume();
    }
    @Override protected void onStart()
    {
        super.onStart();
        mUnityPlayer.start();
    }

    @Override protected void onStop()
    {
        super.onStop();
        mUnityPlayer.stop();
    }

    // Low Memory Unity
    @Override public void onLowMemory()
    {
        super.onLowMemory();
        mUnityPlayer.lowMemory();
    }

    // Trim Memory Unity
    @Override public void onTrimMemory(int level)
    {
        super.onTrimMemory(level);
        if (level == TRIM_MEMORY_RUNNING_CRITICAL)
        {
            mUnityPlayer.lowMemory();
        }
    }

    // This ensures the layout will be correct.
    @Override public void onConfigurationChanged(Configuration newConfig)
    {
        super.onConfigurationChanged(newConfig);
        mUnityPlayer.configurationChanged(newConfig);
    }

    // Notify Unity of the focus change.
    @Override public void onWindowFocusChanged(boolean hasFocus)
    {
        super.onWindowFocusChanged(hasFocus);
        mUnityPlayer.windowFocusChanged(hasFocus);
    }

    // For some reason the multiple keyevent type is not supported by the ndk.
    // Force event injection by overriding dispatchKeyEvent().
    @Override public boolean dispatchKeyEvent(KeyEvent event)
    {
        if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
            return mUnityPlayer.injectEvent(event);
        return super.dispatchKeyEvent(event);
    }

    // Pass any events not handled by (unfocused) views straight to UnityPlayer
    @Override public boolean onKeyUp(int keyCode, KeyEvent event)     { return mUnityPlayer.injectEvent(event); }
    @Override public boolean onKeyDown(int keyCode, KeyEvent event)   { return mUnityPlayer.injectEvent(event); }
    @Override public boolean onTouchEvent(MotionEvent event)          { return mUnityPlayer.injectEvent(event); }
    /*API12*/ public boolean onGenericMotionEvent(MotionEvent event)  { return mUnityPlayer.injectEvent(event); }

4.4 开启通信开关进行通信

这里用开始游戏地方的样例代码

if ( mUnityPlayer != null)
mUnityPlayer.resume()  //打开开关

//向Unity 发送消息参数。
UnityHelper.roomDataForUnity(
mapId.toString(),
detailModel.mapName,
detailModel.mapMd5,
detailModel.mapScreenSchema.toString(),
detailModel.thumb270x153,
if (StringUtil.isEmpty(detailModel.mapCreateUserNickName)) "" else detailModel.mapCreateUserNickName)
//进入游戏
UnityHelper.enterGameForUnity()

4.5 关闭通信开关

  override fun onPause() {
        super.onPause()
        if (isGameSwitch && mUnityPlayer != null) {
            mUnityPlayer.pause() //在生命周期中关闭
        }
    }

Tips
通信开关,一直处于开启状态,会造成界面卡顿。

5.Unity集成需要修改的文件

替换Unity最新导出的Unity_Module 中assert文件夹全部内容,进入Assert文件夹里面修改config.json,config_en.json,config_plat.json,config_versionType.json四个文件中相应的配置与对应环境匹配。

海外版。需要额外替换清单文件中unity.build-id对应的值value,否则会导致obb合成失败,app模块下,AndroidManifest.xml

 <meta-data
            android:name="unity.build-id"
            android:value="5402c169-290b-44af-aa8a-378569ae6916" />
6.Unity通信步骤

1.进入新的activity,关闭上一个activity类中unity通信,将上一个类中mUnityPalyer对象移到新的activity中使用。(mUnityPalyer 全局唯一)

2.在新的activity中奖unity-player 对象添加到新的activity,unity容器中。

3.在新的activity中需要进行通信地方,调用unity-player.resume( ) 方法开启通信开关(这里会有延时)

4.进行unity通信,发送message给unity

5.在MainActivity中处理Unity对activity的响应信息,编写分发逻辑。(EvenBus 进行通知),将响应信息分发到发起通信的类中,进行处理

6.退出新的Activity,在onPause()中暂停消息。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灯塔@kuaidao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值