【真机Bug】异步加载资源未完成访问单例导致资源创建失败

1.错误表现描述

抽卡时,10抽展示界面为A。抽取内容可能是整卡或者碎片,抽到整卡,会有立绘展示和点击详情的按钮。
点击详情后出现详情页B。【此时界面A预制体被销毁,卡片数据进入数据缓存池】
点击页面B的返回按钮,单例的HuanLingRewardController读取DataPool的内容加载界面。
Bug表现:10抽的抽卡展示界面没有出现。
【P.S. 测试发现,问题在游戏引擎平台上没有任何问题,在真机中稳定复现
image.png

2.错误排查阶段

因为界面B没有显示,那么就可能有下面几种情况

  1. 界面B的最大一级预制体没有创建/或者被隐藏
  2. Grid下的每个Item可能没有被创建成功/或者被隐藏

通过对指定卡片的GameObject进行addWatches 监视 和 对于SetActive位置进行断点。
首先排除了,物品未被激活导致不显示的问题。

然后从返回按钮的点击事件回调,追踪了一下上下文结构。在机器适配过程中发现,代码中并没有专门为webgl编写相关的宏分支。那么初步可以判断问题不是出现在机型适配导致的。

接下来,我在CreateItem方法和HuanLingRewardController脚本的Awake和OnEnable阶段断点。
查看堆栈。追踪一下上下文。
image.png
在绘制界面的必经方法中打印了日志(真机调试,用日志输出)
然后。
对比正常创建10抽界面(第一次十抽后显示)和 详情页返回10抽界面(Bug不显示)的日志
image.png
上图为正常加载界面,可以看到碎片都成功加载了。
image.png
上图为不显示界面的情况。发现HuanLingRewardController.awake 阶段在showDrawResult后执行的。
看看awake做了什么事

 private void Awake(){Debug.LogWarning("HuanLingRewardController.Awake()执行了");m_Instance = this;if (!CheckUI()) return;m_LiHuiView.PlayFinished = OnPlayFinished;m_LiHuiView.UpdateActiveTips = OnUpdateActiveTips;m_AutoActiveTipsTweeners = m_AutoActiveTips.GetComponents<UITweener>();m_AutoActiveTips.gameObject.SetActive(false);}

他对Instance实例初始化了。
因为实际上awake在后面执行,所以此时m_Instace == null ,然后在if (!m_Instance) return; 返回了

 public static void ShowDrawResult(GC_SPIRITS_LOTTERY packet, bool playTweenAnimation = true){Debug.LogWarning("ShowDrawResult执行了");if (!m_Instance) return;m_Instance.InnerShowDrawResult(packet, playTweenAnimation);}

3.错误分析

那么为什么作为单例的Controller的awake阶段会在他的静态方法执行后才初始化。
之前的写法是

 public static void ShowLastReward(){Debug.LogWarning("ShowLastReward()执行了");if (m_LastSpiritsLotteryPacket == null) return;ShowUI(SubPage.Reward,true);HuanLingRewardController.ShowDrawResult(m_LastSpiritsLotteryPacket);}

如果ShowUI是同步加载资源的话,是没有问题的但实际上showUI的基类会调用

private static bool DoShowUI(bool bSync, UIPathData pathData, OnOpenUIDelegate delOpenUI = null, object param = null)

 AssetManager.LoadUI(pathData.path, m_instance.LoadUIBundleFinish, pathData);
//主要是调用了LoadUI
pathData.onOpenUI = delOpenUI;
pathData.param = param;
AssetManager.LoadUI(pathData.path, m_instance.LoadUIBundleFinish, pathData);

而LoadAsset是一个异步加载的原型

public static void LoadAsset(BundleType type, string name, Action<IAssetRef, object> callback, object param){if (string.IsNullOrEmpty(name))return;
#if USE_ABBundleTask task = new BundleTask(OnLoadRemoteAssetFinished);task.AddParam(param);task.AddParam(callback);task.Add(type, name);LoadBundle(task, AssetLoader.LoadQueueType.KEYRES);
#elseif (RemoteBundleManager.IsRemoteBundle(type, name)){BundleTask task = new BundleTask(OnLoadRemoteAssetFinished);task.AddParam(param);task.AddParam(callback);task.Add(type, name);LoadBundle(task, AssetLoader.LoadQueueType.KEYRES);}else if (Zeus.Framework.Asset.LocalAssetStatus.Ready == Zeus.Framework.Asset.AssetManager.GetAssetStatus(GetAssetPath(type, name), GetAssetType(type))){if (callback != null)callback(Zeus.Framework.Asset.AssetManager.LoadAsset(GetAssetPath(type, name), GetAssetType(type)), param);}else{Zeus.Framework.Asset.AssetManager.LoadAssetAsync(GetAssetPath(type, name), GetAssetType(type), callback, param);}
#endif}

说明代码逻辑是先生成的窗口预制体然后,去缓存池中读上一次抽卡保存的结果,然后加载数据刷新面板。
所以现在是异步加载未完成然后就调用了后续的静态方法导致被迫中止。

4.问题解决

所以

HuanLingRewardController.ShowDrawResult(m_LastSpiritsLotteryPacket);

刷数据的逻辑应该放在ShowUI 执行成功的回调函数里。
于是,给方法新增标记,判断是否是第二次加载

HuanLingRewardController.ShowDrawResult(m_LastSpiritsLotteryPacket, false);

ShowUI.cs中

public static void ShowUI(SubPage defaultPage,bool isSecondEnter = false){// 针对绘卷UI进行特殊处理if (StoryScrollMainView.GetInstance()){StoryScrollMainView.GetInstance().NeedShowMenu = false;}if (StoryScrollSubView.GetInstance()){StoryScrollSubView.GetInstance().NeedShowMenu = false;}UIManager.ShowUI(UIInfo.HuanLingRoot, (isSuccess, _) =>{if (isSuccess && Instance){Instance.OnShow(defaultPage);}if (isSecondEnter){HuanLingRewardController.ShowDrawResult(m_LastSpiritsLotteryPacket, false);}});}

在UIManager.ShowUI 执行成功的回调中加入上述代码即可。
这样就保证了在界面预制体加载完成后,才会走刷数据的流程。
出现这样的问题也是因为,手机端异步加载资源的速度受到网络延迟,服务器结点的影响很大。用同步加载的逻辑去思考异步功能肯定是不行的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/714803.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++——模版

前言&#xff1a;哈喽小伙伴们好久不见&#xff0c;这是2024年的第一篇博文&#xff0c;我们将继续C的学习&#xff0c;今天这篇文章&#xff0c;我们来习一下——模版。 目录 一.什么是模版 二.模版分类 1.函数模版 2.类模板 总结 一.什么是模版 说起模版&#xff0c;我们…

高性能通信之Netty

一, 同步IO(BIO)模型的架构 一般针对性能不高的情况下可以使用. 二,异步IO(NIO)模型的架构 多路复用(epoll模型):

【LeetCode:124. 二叉树中的最大路径和 + 二叉树+递归】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

【力扣hot100】刷题笔记Day19

前言 回溯回溯回溯&#xff01;早上整理档案竟然用了桶排序&#xff0c;不愧是算法狂魔们 79. 单词搜索 - 力扣&#xff08;LeetCode&#xff09; DFS class Solution:def exist(self, board: List[List[str]], word: str) -> bool:m, n len(board), len(board[0])# used…

谈谈高并发系统的设计方法论

谈谈高并发系统的设计方法论 何为高并发系统&#xff1f;什么是并发&#xff08;Conurrent&#xff09;&#xff1f;什么是高并发&#xff08;Hight Concurrnet&#xff09;&#xff1f;高并发的衡量指标有哪些&#xff1f; 实现高并发系统的两大板块高并发系统应用程序侧的设计…

腾讯云学生服务器使用教程_申请腾讯云学生机详细流程

2024年腾讯云学生服务器优惠活动「云校园」&#xff0c;学生服务器优惠价格&#xff1a;轻量应用服务器2核2G学生价30元3个月、58元6个月、112元一年&#xff0c;轻量应用服务器4核8G配置191.1元3个月、352.8元6个月、646.8元一年&#xff0c;CVM云服务器2核4G配置842.4元一年&…

还在用Jenkins?快来试试这款简而轻的自动部署软件!

最近发现了一个比 Jenkins 使用更简单的项目构建和部署工具&#xff0c;完全可以满足个人以及一些小企业的需求&#xff0c;分享一下。 Jpom 是一款 Java 开发的简单轻量的低侵入式在线构建、自动部署、日常运维、项目监控软件。 日常开发中&#xff0c;Jpom 可以解决下面这些…

吴恩达机器学习全课程笔记第五篇

目录 前言 P80-P85 添加数据 迁移学习 机器学习项目的完整周期 公平、偏见与伦理 P86-P95 倾斜数据集的误差指标 决策树模型 测量纯度 选择拆分方式增益 使用分类特征的一种独热编码 连续的有价值特征 回归树 前言 这是吴恩达机器学习笔记的第五篇&#xff0c…

《2023跨境电商投诉大数据报告》发布|亚马逊 天猫国际 考拉海购 敦煌网 阿里巴巴

2023年&#xff0c;跨境电商API接口天猫国际、京东国际和抖音全球购以其强大的品牌影响力和市场占有率&#xff0c;稳坐行业前三的位置。同时&#xff0c;各大跨境电商平台消费纠纷问题层出不穷。依据国内知名网络消费纠纷调解平台“电诉宝”&#xff08;315.100EC.CN&#xff…

javaEE--后端环境变量配置

目录 pre 文件准备 最终运行成功结果 后端运行步骤 1.修改setenv文件 2.运行setenv&#xff0c;设置环境变量 3.查看jdk版本 4.修改mysql文件夹下的my文件 前端运行步骤 1.nodejs环境配置 2.查看node和npm版本 3.下载并运行npm 4.注册登录 pre 文件准备 最终运行…

VR转接器:破解虚拟与现实边界的革命性设备

VR转接器&#xff0c;这一革命性的设备&#xff0c;为虚拟现实体验带来了前所未有的自由度。它巧妙地连接了虚拟与现实&#xff0c;使得用户在享受VR眼镜带来的奇幻世界的同时&#xff0c;也能自由地在现实世界中活动。这一设计的诞生&#xff0c;不仅解决了VR眼镜续航的瓶颈问…

GO结构体

1. 结构体 Go语言可以通过自定义的方式形成新的类型&#xff0c;结构体就是这些类型中的一种复合类型&#xff0c;结构体是由零个或多个任意类型的值聚合成的实体&#xff0c;每个值都可以称为结构体的成员。 结构体成员也可以称为“字段”&#xff0c;这些字段有以下特性&am…

STM32 | 零基础 STM32 第一天

零基础 STM32 第一天 一、认知STM32 1、STM32概念 STM32:意法半导体基于ARM公司的Cortex-M内核开发的32位的高性能、低功耗单片机。 ST:意法半导体 M:基于ARM公司的Cortex-M内核的高性能、低功耗单片机 32&#xff1a;32位单片机 2、STM32开发的产品 STM32开发的产品&a…

【论文笔记】Improving Language Understanding by Generative Pre-Training

Improving Language Understanding by Generative Pre-Training 文章目录 Improving Language Understanding by Generative Pre-TrainingAbstract1 Introduction2 Related WorkSemi-supervised learning for NLPUnsupervised pre-trainingAuxiliary training objectives 3 Fra…

Java 网络面试题解析

1. Http 协议的状态码有哪些&#xff1f;含义是什么&#xff1f;【重点】 200&#xff1a;OK&#xff0c;客户端请求成功。 301&#xff1a;Moved Permanently&#xff08;永久移除&#xff09;&#xff0c;请求的URL已移走。Response中应该包含一个Location URL&#xff0c;…

steam++加速问题:出现显示443端口被 vmware-hostd(9860)占用的错误。

目录 前言&#xff1a; 正文&#xff1a; 前言&#xff1a; 使用Steam对GitHub进行加速处理时&#xff0c;建议使用2.8.6版本。 下载地址如下&#xff1a;Release 2.8.6 BeyondDimension/SteamTools GitHub 下载时注意自己的系统位数 正文&#xff1a; 使用GitHub时会使…

NOC2023软件创意编程(学而思赛道)python初中组初赛真题

软件创意编程 一、参赛范围 1.参赛组别:小学低年级组(1-3 年级)、小学高年级组(4-6 年级)、初中组。 2.参赛人数:1 人。 3.指导教师:1 人(可空缺)。 4.每人限参加 1 个赛项。 组别确定:以地方教育行政主管部门(教委、教育厅、教育局) 认定的选手所属学段为准。 二、…

蓝桥杯Java B组历年真题(2013年-2021年)

一、2013年真题 1、世纪末的星期 使用日期类判断就行&#xff0c;这里使用LocalDate&#xff0c;也可以使用Calendar类 答案 2099 使用LocalDate import java.time.LocalDate; import java.time.format.DateTimeFormatter; // 1:无需package // 2: 类名必须Main, 不可修改p…

CentOS7 Hive2.3.8安装

CentOS7 Hive2.3.8 安装 建议从头用我的博客&#xff0c;如果用外教的文件到 一、9)步骤了&#xff0c;就用他的弄完&#xff0c;数据库不一样&#xff0c;在9步骤前还能继续看我的 一、 安装MySQL 0.0&#xff09;查询mariadb,有就去0.1&#xff09;&#xff0c;没有就不管…

python3装饰器

装饰器 它允许你修改函数或类的行为&#xff0c;而不更改其源代码。实质上&#xff0c;装饰器是接受另一个函数作为参数并返回一个包装原始函数的新函数。这样&#xff0c;你可以在不修改原始函数的情况下&#xff0c;添加一些额外的功能或逻辑。 def time_cost(func):"…