尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

CocosCreator H5游戏自定义启动页实战:从静态到动态进度条

CocosCreator H5游戏自定义启动页实战:从静态到动态进度条 之前接了一个H5营销小游戏的项目验收那天甲方盯着加载画面说了一句“这转圈的Logo是你们公司吗”我就知道CocosCreator默认启动页这关躲不过去了。做H5游戏启动页几乎是必然要动的地方不管是为了品牌露出、加载引导还是纯粹不想让玩家面对白屏和那个转了不知道多少年的圈。这篇文章就聊CocosCreator在H5平台下的自定义启动页它到底由谁控制、怎么在不对引擎做危险改动的前提下塞进自己的启动画面、以及把真实加载进度同步到进度条上要避开的那些坑。不管你是刚接触CocosCreator的小白还是已经被启动页折腾过一两次的开发者这篇应该都能给你一套能直接落地的方案。1. 动手前的思路拆解启动页到底由谁控制1.1 H5启动页的加载链路先有什么后有什么要自定义启动页第一步不是写代码而是搞清楚浏览器打开一个CocosCreator构建出来的H5页面时到底经历了什么。用户访问index.html浏览器先下载并解析HTML结构接着按标签顺序加载引擎脚本然后执行入口脚本初始化游戏对象之后才开始加载首包的配置、资源和启动场景。整个链路上有一个非常关键的事实在引擎初始化完成之前Cocos的canvas区域是空的你只能靠HTML和CSS撑场面。很多开发者第一次改启动页就翻车就是因为想当然地在场景脚本里把启动页切开结果发现首场景的onLoad执行时canvas已经初始化了但页面依然一片黑或者启动画面直接闪了一下就消失。原因就在加载时序上——引擎脚本和数据包加载都是异步的启动页的存在时间其实就是“index.html被解析完成”到“游戏首帧渲染出来”之间的这段窗口期。理解了这条链路后面所有的方案取舍都会变得清晰。1.2 三种可选路线换图、改模板、接管DOM针对CocosCreator的H5启动页我常用的思路有三条按劳动强度和可控性从低到高排。第一条路线最省事就是改引擎自带的启动页配置。如果你用的是支持这项配置的版本在项目设置里能找到一个“启动页”相关的选项可以换图片、改背景色、设置显示时间。适合那种“我只需要把Cocos的Logo换成自己的Logo”的团队改动量最小构建出来就生效。第二条路线是改构建模板。CocosCreator构建H5时会生成一份index.html而项目里可以放一个build-templates目录构建平台是web-mobile时构建流程会优先拷贝这个目录下的文件覆盖到产物里。这样你就能完全重写index.html的DOM结构往里面塞自己的启动层。这条路线是真正意义上的“自定义”支持加进度条、加品牌动画、加网络异常提示也是我这篇文章的重点。第三条路线更激进直接接管main.js和场景启动逻辑比如在启动时先加载一个空壳场景由这个场景去预加载真正的游戏场景加载进度做成进度条反馈给玩家。这条路可控性最强但代码侵入面也最大对新手不友好我一般只在前两条路线满足不了需求时才用。实际项目里大多数需求用“改模板自定义加载层”就完全够了。2. 最小可用方案用一个静态启动页跑通全流程2.1 修改构建模板让index.html真正能被“自定义”先做最小方案目标只有一个构建出来的H5页面上加载期间能看到我们自己的品牌画面进入游戏后自动消失。整个过程不碰引擎源码只动模板和场景脚本。在项目根目录下新建build-templates目录如果目标是web-mobile平台就建build-templates/web-mobile目录。第一次可以先用CocosCreator正常构建一次然后把构建产物build/web-mobile里的index.html复制到build-templates/web-mobile里作为修改的底本。这一步很关键模板文件不必从零开始写因为里面的脚本引用路径、插件参数都是构建流程自动填的手抄容易抄漏。接下来就能放心改这份模板里的HTML结构了。构建时会以这份文件为准生成新的index.html引擎脚本和插件注入逻辑不会受影响。这个方案对2.x和3.x版本都适用唯一区别是构建平台目录名要对应好。如果你同时构建桌面版可以再加一个build-templates/web-desktop目录两份模板各改各的互不干扰。2.2 把品牌启动层塞进页面现在给index.html加一个启动层。基本结构就是一个全屏的div里面放品牌Logo、加载提示或者转圈动画。需要注意这个div必须放在Cocos的canvas容器之前或之后都可以但要保证它的zIndex够高、position是fixed或absolute能完整盖住整个游戏区域。我一般直接把启动层放在body子元素的第一位再用CSS把它固定在视口上基本不会出问题。div idapp-splash div classsplash-box img classsplash-logo srclogo.png altlogo / div classsplash-text游戏加载中.../div /div /div这里有一个新手非常容易踩的坑模板里的图片路径。build-templates目录下的文件虽然会被拷贝到构建产物里但img标签里的src是相对路径如果logo.png放在build-templates/web-mobile/的同级目录下构建后它确实会被一起拷贝但如果你像引用项目资源那样写assets/xxx/logo.png构建后基本必挂。最稳妥的做法是把启动页要用的图片放到build-templates/web-mobile目录下src写成相对当前页面路径的地址比如./logo.png。光有画面还不够还得给外部留一个“关闭启动页”的入口。在模板script里放一个全局函数等游戏场景加载起来后调用它来收起启动层script window.hideAppSplash function () { var splash document.getElementById(app-splash); if (splash !splash.classList.contains(splash-hide)) { splash.classList.add(splash-hide); setTimeout(function () { var parent splash.parentNode; if (parent) { parent.removeChild(splash); } }, 400); } }; /script配合简单的CSS过渡隐藏时做一次淡出视觉上比突然消失自然得多。2.3 在首场景里精准淡出避免闪白启动层准备好了什么时候关闭它答案是从逻辑上要等“游戏真正能看了”再关。最简单的做法是在首场景的某个组件里等onLoad或start执行完确认场景已经初始化再调用window.hideAppSplash()。cc.Class({ extends: cc.Component, onLoad() { // 这里可以做首场景需要的数据初始化 }, start() { if (window.hideAppSplash) { window.hideAppSplash(); } } });从onLoad到start之间虽然就隔了一帧但视觉上区别还是有的。onLoad里往往还在创建节点、挂组件、加载数据画面并没有准备好此时把启动层撤掉很容易闪黑或闪白。start执行时首帧渲染已经就绪画面内容基本定下来了再关启动层就稳很多。另外启动层淡出期间下面露出来的游戏画面底色最好和启动层背景色接近不然淡出时会看到很突兀的色块跳动。我一般会把Cocos项目设置里的默认背景色和启动层背景色调成同一个颜色这一条对追求细节的团队尤其有用。3. 进阶版带真实加载进度的动态启动页3.1 拿到首场景预加载进度的正确姿势静态版本跑通之后你会发现玩家如果网络慢启动页上那个“游戏加载中”的文字会一直挂着不知道还要等多久。这时候就需要真实进度条了。Cocos引擎其实提供了一个非常合适的API来做这件事预加载场景。2.x版本里可以这么用cc.director.preloadScene(Game, function (completedCount, totalCount) { var progress completedCount / totalCount; if (window.updateSplashProgress) { window.updateSplashProgress(progress); } }, function () { if (window.updateSplashProgress) { window.updateSplashProgress(1); } cc.director.loadScene(Game); });3.x版本里的思路类似但底层模块换成了assetManager。可以直接用assetManager.loadBundle预加载远程包或者继续用director.preloadScene回调里的参数结构在3.x中也不完全一样。我的建议是先用官方文档确认你当前版本里preloadScene的回调参数结构然后在本地电脑上打开浏览器开发者工具在Network面板里观察资源加载验证进度回调是否真的在走。这部分的实操体验是进度回调里的completedCount和totalCount针对的是当前场景相关资源不是整个游戏包的全部资源所以进度条走到100%后还会有一段“场景初始化”的时间这很正常。如果你希望进度条更稳可以在代码里手动把进度最大值限制到90%或95%等场景真正切换完成后再一次性补到100%视觉上会更舒服。3.2 把进度同步到启动页DOM拿到进度数值之后剩下的事就简单了——把这个数值同步给启动页里的进度条。做法和静态版本关闭启动页的思路一样通过全局函数沟通把数值喂给启动层。在模板的script里增加一个更新函数script window.updateSplashProgress function (p) { var bar document.getElementById(splash-progress-bar); var text document.getElementById(splash-progress-text); if (bar) { bar.style.width Math.floor(p * 100) %; } if (text) { text.innerText Math.floor(p * 100) %; } }; /script然后在游戏代码里把上一节的preloadScene进度回调接上去。这个方案和静态版本是兼容的进度条更新和关闭启动层各管各的互不干扰。需要提醒的是启动页里的进度条如果用的是transform的scale或translate来驱动宽度记得加上过渡动画不然进度会一截一截地跳观感很差。用transition: width 0.2s ease-out这类CSS一秒内多次调用也能平滑过渡实测下来效果不错。3.3 引擎自带启动页配置有什么用为什么还是建议自己写既然能自己在模板里写进度条那Cocos自带的那个启动页配置还有没有必要开我个人看法是“能不全开就不全开”。自带的启动页配置适合快速换图但它的样式、动效、交互都是引擎定好的你想加个“点击屏幕跳过”或网络异常提示基本没法在不改模板的前提下做到。而且如果你自己写了启动层又不小心同时开启了引擎自带的加载动画页面上很可能出现两层加载UI观感非常乱。如果你暂时不需要自定义进度条只想把默认那个Logo换掉那引擎自带配置是最快的。需要做任何额外动效或交互就果断切到自己写启动层这条路上来。两条路二选一不要混用这是我折腾了几次之后总结出的最省心的原则。4. H5环境适配与问题排查实战4.1 微信、公众号、APP内嵌WebView里的适配点H5游戏最大的特点就是运行环境不可控。你以为用户会用Chrome打开实际上可能是在微信对话框里点开或者被嵌进了某个APP的WebView里。这些环境下自定义启动页最容易翻车的地方有几个。第一个是视口单位的问题。CSS里的100vh在很多安卓WebView和微信内置浏览器里表现不稳定底部虚拟导航栏显示和隐藏时高度会跳启动页上的背景跟着一颤一颤的。解决方法是别把启动层的高度写死成100vh用position: fixed加top: 0; bottom: 0; left: 0; right: 0;让元素跟随视口布局比依赖vh稳得多。第二个是底部安全区。如果游戏需要嵌入带有底部工具栏的APP启动页上的按钮可能被系统手势条或APP自带的栏遮住。给关键元素加padding-bottom: env(safe-area-inset-bottom)基本是标配了。很多游戏启动页会放“点击进入”按钮这个适配要提前做好。第三个容易被忽视的点是自动播放策略。在微信内置浏览器里如果启动页结束后立刻要播放背景音乐多半会被拦截。启动页期间不要主动调用Cocos的音频API也不要尝试在用户点击之前播放任何多媒体资源否则控制台会刷一堆警告严重的还会影响后续逻辑。4.2 白屏、进度卡死、缓存不生效的排查清单改完启动页之后最常见的三个问题就是白屏、进度卡死和缓存不生效。逐个说。白屏通常是启动层盖住了canvas但游戏本身没有正常初始化。先在浏览器开发者工具的Console面板看有没有报错再看Network里资源是不是大片404。如果是八成是模板里的脚本引用路径或插件配置写错了检查构建产物和源模板的差异。进度卡死往往是预加载的资源里混进了失败的请求比如某个远程图片域名不允许跨域访问或者首包资源下载到一半网络断了。进度回调拿到的totalCount是总数失败了它也不会自动跳过进度就卡在那儿。处理方式是在进度回调外部加一个超时判断比如超过8秒还没到100%就显示“网络不稳定点击重试”的按钮而不是让玩家对着卡死的进度条干瞪眼。这个兜底逻辑能用上的人不多但真碰上次弱网环境体验差距非常明显。缓存不生效这个最阴间。你本地改好了index.html部署到测试服务器刷新半天还是旧的启动画面。原因是浏览器对HTML和应用包资源做了强缓存。开发阶段可以在服务器端给index.html配置no-cache强制每次都回到服务器校验发布阶段建议给静态资源加版本号或hash。同时记得在浏览器DevTools里勾选Network面板的Disable cache排除本地缓存干扰。4.3 上线前启动页自查表最后把我每次上线前会过一遍的检查项整理成表按照这个顺序走一遍基本能避免大部分线上事故。检查项验证方式注意事项启动页图片清晰度真机打开游戏对比设计稿图片放在build-templates目录路径用相对路径进度条平滑度浏览器开发者工具切弱网模式观察动画进度更新加上CSS过渡限制最大进度到90%淡出时机首场景start后观察是否闪白淡出动画结束再移除DOM颜色与游戏背景对齐WebView兼容微信、iPhone Safari、安卓Chrome各测一遍高度用fixed定位不依赖100vh网络超时兜底挂代理模拟断网观察启动页表现8-10秒超时显示重试按钮缓存策略发布后强制刷新一次再正常刷新一次index.html禁用缓存资源文件加hash音频自动播放真机微信环境进入游戏触发音乐用户点击后再初始化音频启动页内不调音频API这张表其实也是我每次接到H5启动页需求时的验收清单做过的项目里十个有八个最后都栽在“缓存没更新”和“WebView高度抖动”这类看起来不起眼的问题上。说点个人体会。我现在做CocosCreator的H5项目从第一个版本就会把build-templates/web-mobile目录建好哪怕第一版只是把index.html原封不动放进去等后面需求方说“启动页要加一句活动文案”“加一个版本公告”直接改模板就能快速验证不用重新搭一套流程。自定义启动页这个需求本身没有太高深的技术门槛最考验人的是加载时序和理解各个环境下的运行差异。先把静态版本跑通再升级进度条最后再处理环境适配一步步来翻车概率会小很多。
返回列表