作者

大家好,我叫Jack冯;
本人20年硕士毕业于广东工业大学,于2020年6月加入37手游安卓团队;目前主要负责海外游戏发行安卓相关开发。

系列目录

  • 游戏优化系列一:海外谷歌应用适配相关

  • 游戏优化系列二:Android Studio制作图标教程

  • 游戏优化系列三:Unity游戏的黑屏问题解决方法 (本章讲解

本文目录

一、背景
二、分析及解决
1、生命周期分析
(1)黑屏情况
(2)解决方法
(3)正常显示
2、涉及方法解析
(1)onWindowFocusChanged (boolean hasFocus)
(2)Android生命周期
(3)对比Android原生工程
(4)unity脚本生命周期
(5)分析脚本生命周期
三、结论

一、背景

在Unity游戏工程中,经常遇到这样的问题:打开登录弹框时,点击Home键先处理其他事宜再返回,发现屏幕黑屏;或者打开了其他接受输入焦点的对话框或弹出窗口,点击返回键时发生屏幕黑屏,需要触摸屏幕(获得焦点)才能正常显示。

具体情形见下图:

1、黑屏情况(UnityDemo):

2、 正常显示(UnityDemo):

二、分析及解决

1、生命周期分析

(1)黑屏情况(UnityDemo):

其中,生命周期顺序如下:

- 打开页面:onCreate–onStart–onResume–onWindowFocusChanged:true

- 点击登录:–onWindowFocusChanged:false

- 点击Home返回:–onPause

- 重新进入:–onRestart–onStart–onNewIntent–onResume–onWindowFocusChanged:false(此时app页面出现黑屏)

(2)解决方法

在游戏主活动UnityPlayerActivity中,重写onStart()方法,添加获取焦点的方法,可避免黑屏。

    @Overrideprotected void onStart() {super.onStart();this.mUnityPlayer.resume();onWindowFocusChanged(true);}
(3)正常显示(UnityDemo):

其中,生命周期顺序如下:

- 打开页面:onCreate–onStart–onWindowFocusChanged:true–onResume–onWindowFocusChanged:true

- 点击登录:–onWindowFocusChanged:false

- 点击Home返回:–onPause

- 重新进入:–onRestart–onStart–onWindowFocusChanged:ture–onNewIntent–onResume(此时app页面正常显示)

由上可见,二者生命周期的异同在于,是否在调用onStart后调用一次onWindowFocusChanged:true,来获取当前窗口的焦点,实现正常交互。

2、涉及方法解析

(1)onWindowFocusChanged (boolean hasFocus)

当activity的当前窗口获得或失去焦点时调用,hasFocus == true表示当前窗口获得焦点,false则表示失去焦点。用法:

onWindowFocusChanged (true);

- eg:打开页面,当前activity处于活动栈最上层的活动,获得焦点–onWindowFocusChanged:ture;

- 点击登录,弹框覆盖在原activity的上层,原activity失去焦点 --onWindowFocusChanged:false;(不仅限弹框,还可以是其他获取焦点的页面)

- 此后点击Home键、再返回app,原activity仍然是失去焦点的状态(如果没有手动重新获取焦点),当前页面显示黑屏。

注意

​ onWindowFocusChanged方法提供了有关全局焦点状态的信息,该状态独立于活动生命周期进行管理。因此,虽然焦点更改通常与生命周期更改有某种关系(停止的活动通常不会获得窗口焦点),但您不应依赖此处回调与其他生命周期方法(如onResume()中的回调)之间的特定顺序。

​ 但是,一般来说,前台活动具有窗口焦点。除非它显示了其他接受输入焦点的对话框或弹出窗口,在这种情况下,当其他窗口有焦点时,活动本身就没有焦点。同样,系统可能会显示系统级窗口(例如状态栏通知面板或系统警报),这些窗口将暂时获得窗口输入焦点,而不会暂停前台活动。

​ 从Android Q开始,在多窗口模式下,可以同时有多个恢复的活动,因此即使上面没有覆盖,恢复状态也不能保证窗口焦点。如果目的是要知道一个活动何时是最活跃的,即用户在所有活动中与之交互的最后一个活动,但不包括非活动窗口(如对话框和弹出窗口),则应使用OnTopheMedActivityChanged(Boolean value)。

(2)生命周期方法简析

- onCreate (Bundle savedInstanceState):活动创建时调用一次,用于初始化当前活动数据和绑定页面的组件等。参数Bundle:如果活动在关闭后重新初始化,此参数则包含其最近一次调用 onSaveInstanceState(Bundle)存储的数据。

- onStart ():在活动创建方法onCreate(Bundle)或重新启动方法onRestart()之后调用,开始绘制视图、动画等,呈现给用户,其后一般调用onResume()。(可视化状态)

- onResume ():在onRestoreInstanceState()、onRestart()或onPause()之后调用,当前活动位于活动栈的顶部,即将开始与用户进行交互、准备好接收输入事件。(还不能响应输入事件)

- onPause ():活动仍在屏幕上可见,但用户不再与其交互时进行调用,eg:弹框等页面覆盖了当前活动时。

- onStop ():当活动在屏幕上不可见时调用,eg:点击home键返回桌面

- onRestart ():在 onStop ()方法后,重新打开原activity时调用,其后一般调用onStart ()和onResume ()

- onDestroy ():在销毁活动之前执行任何最后的清理时调用。一般是活动即将结束(调用 finish()),或系统暂时销毁了此活动实例以节省空间

(3)对比Android原生工程

图为原生工程的AndroidDemo。对比UnityDemo,生命周期方法执行虽一致、焦点丢失情况则不相同。

为了进一步对比,下面引入unity脚本的常见生命周期方法。

(4)unity脚本生命周期

unity脚本的常见生命周期方法如下:

– Awake:始终在任何 Start 函数之前并在实例化组件之后调用此函数。(如果游戏对象在启动期间处于非活动状态,则在激活之后才会调用 Awake。)
– OnEnable:(仅在对象处于激活状态时调用)在启用对象后立即调用此函数。在创建 MonoBehaviour 实例时(例如加载关卡或实例化具有脚本组件的游戏对象时)会执行此调用。
– OnLevelWasLoaded:场景全部加载完成后
– Start:仅当启用脚本实例后,才会在第一次帧更新之前调用 Start。

– FixedUpdate:调用 FixedUpdate 的频度常常超过 Update。如果帧率很低,可以每帧调用该函数多次;如果帧率很高,可能在帧之间完全不调用该函数。
– Update:每帧调用一次 Update。这是用于帧更新的主要函数。
– LateUpdate:每帧调用一次 LateUpdate__(在 Update__ 完成后)。
– OnGUI:每帧调用多次以响应 GUI 事件。首先处理布局和重新绘制事件,然后为每个输入事件处理布局和键盘/鼠标事件。

– OnApplicationPause:一帧最后时调用,调用后会再触发一帧以刷新图像和切换暂停状态
– OnApplicationQuit:在退出应用程序之前在所有游戏对象上调用此函数。在编辑器中,用户停止播放模式时,调用函数。

– OnDisable:行为被禁用或处于非活动状态时,调用此函数。
– OnDestroy:对象存在的最后一帧完成所有帧更新之后,调用此函数(可能应 Object.Destroy 要求或在场景关闭时销毁该对象)。

(5)分析脚本生命周期

这里将生命周期方法在UnityDemo中打印出来,主要对比黑屏情况下的生命周期情况。

具体日志如下:

//android生命周期
E/UnityPlayerActivity: onCreate
E/UnityPlayerActivity: onStart
E/UnityPlayerActivity: onResume
E/UnityPlayerActivity: onWindowFocusChanged:true//unity脚本生命周期
I/Unity: UnityPlayerActivity Awake
...
I/Unity: UnityPlayerActivity OnApplicationPause:False
I/Unity: UnityPlayerActivity OnApplicationFocus:True
I/Unity: UnityPlayerActivity start//点击home键
E/UnityPlayerActivity: onWindowFocusChanged:false
I/Unity: UnityPlayerActivity OnApplicationFocus:FalseE/UnityPlayerActivity: onPause
I/Unity: UnityPlayerActivity OnApplicationPause:True
...//再次返回app
E/UnityPlayerActivity: onRestart
E/UnityPlayerActivity: onStart
E/UnityPlayerActivity: onResume//***注意***,这里unity脚本生命周期方法并没有继续执行!

三、总结

综合分析,从桌面返回游戏App时,由于unity丢失焦点(I/Unity: UnityPlayerActivity OnApplicationFocus:False ),脚本没有执行,即无法渲染游戏画面对象,致使黑屏。

如果根据第二点添加获取焦点方法后,由下图可以看到继续执行的unity脚本生命周期方法,先获取到焦点、中止pause状态并绘制页面进行正常显示。即工程重新获取焦点后才会绘制图像。

I/Unity: UnityPlayerActivity OnApplicationFocus:True
I/Unity: UnityPlayerActivity OnApplicationPause:False

游戏优化系列三:Unity游戏的黑屏问题解决方法相关推荐

  1. html5 游戏 黑屏,只狼进游戏黑屏怎么办?黑屏问题解决方法介绍

    只狼进游戏黑屏怎么办?黑屏问题解决方法介绍 2019-03-22 16:26 作者:佚名 来源:本站整理 浏览:3343 只狼进游戏黑屏怎么办?黑屏是新上市游戏最常遇到的问题之一,所以只狼的玩家也会遇 ...

  2. VMware虚拟机下Ubuntu Cheese黑屏问题解决方法的2各案例。

    VMware虚拟机下Ubuntu Cheese黑屏问题解决方法的2各案例. VMware虚拟机下Ubuntu Cheese黑屏问题解决方法 案例1: 试试安装 sudo apt install web ...

  3. win10安装账户卡住_Win10安装出现卡死或黑屏怎么办?Win10安装卡死或黑屏问题解决方法...

    Win10安装出现卡死或黑屏怎么办?Win10已经面向全球进行推送,很多朋友都选择在第一时间进行升级,但是在Windows 10安装卡死或黑屏导致无法启动问题.那么该如何解决呢?下面小编就给大家分享下 ...

  4. VMware安装CentOS7时遇到的黑屏问题解决方法

    解决方案 在网上查阅后发现,有人遇到了和我一样的问题.原因是BIOS的Virtualization Technology设置被禁止了,需要进入BIOS将其设置为Enabled.(不同电脑进入BIOS的 ...

  5. Android 屏幕截图黑屏问题解决方法

    以下两种截屏方法可能由于尺寸没有设置默认过大系统不予处理. public static Bitmap convertViewToBitmap(View view, int bitmapWidth, i ...

  6. 一致吗 驱动_外国不过春节?AMD驱动再更新,解决BUG,游戏不闪退,重启不黑屏...

    AMD依然是那个AMD,驱动自然也还是那个驱动. 相对于英特尔大的驱动来说,AMD的驱动也继承了ATI当年催化剂驱动的<优良传统>. 真的是BUG不断. 上一个版本的驱动的实在锤问题: & ...

  7. 荒岛求生游戏显示服务器不行,《荒岛求生》黑屏解决方法

    孤岛求生进入游戏黑屏怎么回事 电脑配置太低,或者下载的盗版 荒野求生更新后黑屏.闪退解决方法 这种情况一般是<荒野求生>数据包的问题,含数据包的游戏更新时,数据包也需要更新,如果你只更新了 ...

  8. 游戏开发 unity3d python_游戏研发系列 Unity3D/2D游戏开发从0到1 第2版.pdf

    作 者 :刘国柱著 出版发行 : 北京:电子工业出版社 , 2018.01 ISBN号 :978-7-121-33499-3 页 数 : 507 丛书名 : 游戏研发系列 原书定价 : 99.00 开 ...

  9. steam游戏上架流程三: 游戏的发布配置与测试

    参考: steamworks.net 官方文档的说明 http://steamworks.github.io/gettingstarted/ steam游戏上架流程一:使用官方SDK上传游戏  htt ...

最新文章

  1. phpcms v9 为分类和内容添加伪静态
  2. 使用ABAP代码获得Netweaver环境变量
  3. FireBug实用指南
  4. 解决Mac无法编辑 .bash_profile文件与使用sudo时permission denied报错
  5. 广东计算机科学导论考试试卷,计算机科学导论试题A答案
  6. Mac系统下安装svn环境方法
  7. 一个Keil工程包含的内容
  8. 北理乐学大学计算机实验报告,北理乐学实验六.doc
  9. Python实现四阶龙格库塔法求解Ricatti方程
  10. 数据库sql优化总结之1-百万级数据库优化方案+案例分析
  11. confirm() 中写html,confirm用法 Confirm……that……
  12. OpenStack部署(未完成)
  13. 电商技术中企业数据总线ESB和注册服务管理的区别
  14. 国外3个设计师插画等必备PNG免扣素材网站分享
  15. NIOSII 软核的流水灯
  16. iOS 15提示“此App的开发者需要更新APP以在此IOS版本上正常工作”
  17. 如何区分奋斗者和奋斗b?
  18. 2022 ICLR | Geodiff:分子构象几何扩散生成模型
  19. 中国权证市场可行性及概念诠释
  20. python数学公式的输入

热门文章

  1. 用于平抑可再生能源功率波动的储能电站建模及评价(Matlab代码实现)
  2. hbase merge regions
  3. c语言程序设计是什么国二,国二c语言考什么
  4. 医疗时鲜资讯:关注新医改动态
  5. 英语教材提取单词制作生词表
  6. WPF 实现3维图片墙相关展示效果(凹面墙,凸面墙)
  7. 如何理解拿得起放得下?
  8. 白马培训机构招生管理系统-数据流图(DFD)
  9. source insight添加shell支持
  10. 对linux内核中GDT和LDT的理解