Cocos Creator 3.0.0 实现 web-mobile 透明背景的完整指南
1. 为什么要在 Cocos Creator 3.0.0 里折腾透明背景做过 H5 小游戏或者互动营销页的朋友大概率都遇到过这种需求游戏画面不是全屏铺满而是作为一个图层叠在网页已有的背景之上或者嵌在某个卡片、弹窗、直播间挂件里。这时候如果 Cocos 导出的 web-mobile 包默认带着一块不透明的底色视觉上就会非常突兀——本来想做个悬浮的 3D 模型结果周围糊了一圈黑边或者白底跟页面其他元素完全融不到一起。我最近接手的一个项目就是这种场景一个基于 Cocos Creator 3.0.0 做的轻量互动 Demo需要嵌到已有的网页里网页本身有渐变背景和动态粒子Cocos 画布必须完全透明只保留场景里的模型和 UI。听起来是个很基础的需求但 3.0.0 这个版本比较特殊它正好处在 2.x 到 3.x 引擎架构大改的过渡期渲染管线、构建模板、启动脚本都跟 2.x 完全不是一套东西网上能搜到的教程大多是 2.x 的直接照搬会踩一堆坑。所以这篇东西就是把我从零摸索到跑通的全过程整理出来包括构建模板怎么改、引擎启动参数怎么配、相机和场景要动哪些设置、以及不同浏览器下的兼容性差异。适合正在用 Cocos Creator 3.0.x 做 H5 嵌入、需要透明背景的开发者也适合想搞清楚 3.0 构建产物结构的人。哪怕你用的是 3.4、3.6 这些后续版本思路也是通的只是个别文件路径和 API 名字会有微调我会在关键位置标注出来。先说结论Cocos Creator 3.0.0 实现 web-mobile 透明背景核心是三件事——构建模板里的 CSS 和 HTML 结构、引擎初始化时的alpha与premultiplyAlpha参数、以及场景相机的 clearFlags 设置。三件事缺一不可少一个就会出现背景透明了但模型发黑或者模型正常但背景还是白的这类半吊子状态。下面逐个拆。2. 先搞清楚 3.0.0 的构建产物长什么样2.1 web-mobile 构建目录结构解析在动手改之前必须先把构建出来的东西看明白不然你都不知道该改哪个文件。Cocos Creator 3.0.0 构建 web-mobile 之后build/web-mobile目录下大致是这么个结构build/web-mobile/ ├── index.html # 入口页面 ├── main.js # 引擎启动入口 ├── application.js # 应用配置与启动逻辑 ├── style.css # 页面样式部分版本在 index.html 内联 ├── assets/ # 资源文件 │ ├── main/ │ └── resources/ ├── cocos-js/ # 引擎 JS 文件 │ ├── cc.js │ └── ... └── src/ # 项目脚本编译产物 ├── chunks/ └── ...跟 2.x 最大的区别在于3.0 把启动逻辑拆成了main.js和application.js两层。main.js负责加载引擎application.js里有一个Application实例的配置对象里面包含了cc.Application的启动参数。透明背景相关的alpha、premultiplyAlpha这些开关就在这个配置对象里。而index.html里则定义了承载游戏的 canvas 容器以及页面级的 CSS。默认情况下Cocos 会给body和 canvas 都设置不透明背景这就是为什么你直接构建出来永远是白底或黑底。2.2 默认配置为什么是不透明的很多人会问我场景里相机 clearFlags 都设成不清理颜色了为什么导出来还是白的原因就在于引擎初始化时创建的 WebGL context 默认alpha: false。这个参数决定了 canvas 的绘图缓冲区有没有 alpha 通道。如果alpha: false那么无论你怎么设置相机、怎么改 CSScanvas 本身就是一个不透明的位图透明信息在底层就被丢掉了。Cocos Creator 3.0.0 的默认模板里这个参数是关掉的因为绝大多数游戏都需要不透明背景开着 alpha 通道会带来一点点性能开销虽然很小而且可能引发一些混合模式的显示问题。所以引擎默认帮你选了不透明这个更稳妥的选项。我们要做的就是把它打开并且处理好随之而来的预乘 alpha 问题。提示alpha和premultiplyAlpha是两个必须一起考虑的参数。只开alpha不开premultiplyAlpha半透明边缘会出现黑边两个都开但相机设置不对又可能出现颜色发灰。这个后面会详细讲。3. 修改构建模板一劳永逸的做法3.1 找到并定制构建模板Cocos Creator 3.0.0 允许你自定义构建模板这样每次构建都会用你的模板不用每次手动改build目录手动改的话下次构建就被覆盖了。模板的位置在项目根目录下项目根目录/ └── build-templates/ └── web-mobile/ ├── index.html ├── main.js └── style.css如果build-templates目录不存在就自己建一个。然后把引擎自带的模板文件复制过来改。引擎自带模板的位置在 Cocos Creator 安装目录下大致路径是CocosCreator安装目录/resources/3d/engine/templates/web-mobile/不同安装方式路径可能略有差异Mac 和 Windows 也不一样。最省事的办法是先正常构建一次把build/web-mobile里的index.html、main.js、style.css复制到build-templates/web-mobile/下然后在这个副本上改。这样保证你改的就是当前版本实际用的模板不会因为版本差异导致文件对不上。3.2 改 index.html让页面和 canvas 都透明打开模板里的index.html重点看body和 canvas 容器的样式。默认大概是这样style body { margin: 0; padding: 0; background-color: #000; /* 或者白色 */ } #GameDiv { background-color: #000; } /style要改成透明把背景色去掉或者设成transparentstyle html, body { margin: 0; padding: 0; width: 100%; height: 100%; background: transparent; overflow: hidden; } #GameDiv { background: transparent; } #GameCanvas { background: transparent; } /style这里有个细节html和body都要设background: transparent只设 body 有时候在某些浏览器下还是会有白底因为 html 元素本身有默认背景。另外#GameDiv和#GameCanvas的 id 名字要跟你模板里实际的一致3.0.0 默认容器 id 是GameDivcanvas 是GameCanvas但如果你改过就得对应上。还有一点如果你的游戏是要嵌在别的页面里比如 iframe 或者某个 div 内那index.html的透明只是基础外层容器的背景也得是透明的否则你这边透明了外层一个白底照样给你盖住。这个锅不在 Cocos但排查的时候经常有人忽略。3.3 改 main.js打开 alpha 通道main.js是引擎启动的关键。3.0.0 的main.js里会创建一个Application实例类似这样const app new Application({ // ... 其他配置 });但真正控制 WebGL context 创建参数的地方在application.js或者main.js里对cc.game.init的调用附近。3.0.0 的写法比较绕我实测下来最可靠的改法是在main.js里找到settings或者game.init相关的配置加上alpha和premultiplyAlpha。具体来说在main.js中你会看到类似这样的结构System.import(./application.js).then(({ Application }) { return new Application(); }).then((app) { // ... });而application.js里会有export class Application { constructor() { // ... } init() { // ... game.init({ // 各种配置 }); } }你要做的是在game.init的配置对象里加上game.init({ alpha: true, premultiplyAlpha: true, // ... 其他原有配置 });如果application.js是压缩过的或者结构不好找还有一个更直接的办法在main.js的最顶部引擎加载之前直接改cc.game的默认配置。不过 3.0.0 的模块加载机制下cc全局对象不一定在main.js执行时就已经挂上所以这个办法不太稳。我推荐还是老老实实改application.js里的game.init配置。注意premultiplyAlpha设成true之后所有纹理和颜色在混合时都会按预乘 alpha 处理。如果你的美术资源是按非预乘 alpha 做的可能会出现边缘发暗或者颜色偏移。解决办法是要么统一美术规范用预乘要么在加载纹理时单独设置。这个坑我在第 5 节会展开讲。3.4 构建模板的生效验证改完模板后重新构建一次然后打开build/web-mobile/index.html检查用浏览器开发者工具看body和 canvas 的 computed stylebackground 应该是rgba(0, 0, 0, 0)或者transparent。在 console 里执行document.getElementById(GameCanvas).getContext(webgl).getContextAttributes()看返回的对象里alpha是不是truepremultipliedAlpha是不是true。如果这两步都对说明模板层面已经改到位了。接下来就是场景和相机层面的事。4. 场景与相机设置透明背景的另一半4.1 相机 clearFlags 的正确设置光改模板和引擎参数还不够场景里的相机如果还在清理颜色缓冲区那画面照样是不透明的。在 Cocos Creator 3.0.0 里选中场景中的 Main Camera在属性检查器里找到ClearFlags这一项。ClearFlags 有四个选项选项含义透明背景该选哪个SOLID_COLOR用纯色清理不要选DEPTH_ONLY只清理深度可以选DONT_CLEAR不清理可以选SKYBOX用天空盒清理不要选做透明背景推荐选DEPTH_ONLY。为什么不是DONT_CLEAR因为DONT_CLEAR在某些设备上会导致上一帧的残留没被清掉出现拖影。DEPTH_ONLY会清理深度缓冲但不碰颜色缓冲这样颜色缓冲里保留的就是透明信息同时深度又干净是最稳的选择。如果你场景里有多个相机比如一个 3D 相机加一个 UI 相机那每个相机的 clearFlags 都要检查。UI 相机通常用DEPTH_ONLY或者DONT_CLEAR3D 主相机用DEPTH_ONLY。只要有一个相机设成了SOLID_COLOR它就会把整个画面刷成不透明。4.2 相机背景色与 alpha 的关系有人会想我把相机的 ClearColor 的 alpha 设成 0 不就行了在 3.0.0 里相机的 ClearColor 确实有 RGBA 四个通道理论上把 A 设成 0 就是透明。但实测下来如果引擎的 WebGL context 没开 alpha 通道这个 alpha 值是无效的最终还是会按不透明处理。所以 ClearColor 的 alpha 只能作为辅助前提是 context 已经开了 alpha。另外即使 context 开了 alphaClearColor 的 RGB 值也会影响最终效果。比如你设成(0, 0, 0, 0)在预乘 alpha 模式下黑色乘以 0 还是 0没问题但如果你设成(1, 1, 1, 0)白色乘以 0 也是 0理论上也没问题。但有些浏览器在处理非预乘的(1,1,1,0)时会出现白色残留。所以保险起见ClearColor 设成(0, 0, 0, 0)也就是全透明黑。4.3 场景中其他可能影响透明的因素除了相机还有几个地方容易埋雷场景的 ambient 环境光如果环境光颜色不是黑色且强度不为 0可能会给透明区域染上一层颜色。不过这个通常只影响模型不影响背景透明但如果你发现透明区域有淡淡的色调可以检查一下。后处理效果3.0.0 的后处理如果开了 bloom 之类的可能会把透明区域也处理进去导致边缘发光或者背景变灰。透明背景场景建议先关掉后处理确认基础透明没问题再逐个开。UI 的 Canvas 组件UI 相机对应的 Canvas 如果带了不透明的背景图或者全屏遮罩也会挡住透明。检查一下 UI 层级里有没有全屏的 Sprite 或者 Graphics。5. 预乘 Alpha 的坑与纹理处理5.1 预乘 alpha 到底是什么这个概念不搞清楚透明背景做出来大概率是能透但边缘发黑或者半透明物体颜色不对。我用个生活化的类比解释想象你有一张画在玻璃上的画玻璃本身是透明的。非预乘 alpha就像是你先在玻璃上画颜色然后告诉别人这块玻璃的透明度是 50%。别人看的时候需要自己把颜色和透明度乘一下才知道最终看到什么。预乘 alpha则是你在画的时候就已经把颜色乘以透明度画上去了别人直接看就行不用再算。在计算机图形里预乘的好处是混合公式更简单、边缘更干净坏处是如果资源没按预乘做颜色就会偏。Cocos Creator 3.0.0 里premultiplyAlpha: true意味着引擎期望所有纹理和颜色都是预乘的。但很多美术导出的 PNG 是非预乘的直接拿来用就会出问题。5.2 纹理导入时的 alpha 设置在 Cocos Creator 3.0.0 的资源管理器里选中一张带透明通道的 PNG属性检查器里会有Premultiply Alpha这个选项在 Texture 或 SpriteFrame 的设置里。默认可能是勾选或者不勾选取决于版本。我的建议是如果你在引擎启动参数里开了premultiplyAlpha: true那所有带透明的纹理都要勾上 Premultiply Alpha保持一致。否则就会出现背景透明了但模型边缘一圈黑的经典问题。如果纹理很多一个个改太累可以写个编辑器扩展脚本批量处理或者干脆在美术导出环节就统一规范。这个在项目初期定好后期能省很多事。5.3 半透明物体的混合模式预乘 alpha 下半透明物体的混合模式也要注意。Cocos Creator 3.0.0 的材质里混合模式默认是SRC_ALPHA, ONE_MINUS_SRC_ALPHA这是非预乘的公式。如果开了预乘应该改成ONE, ONE_MINUS_SRC_ALPHA。不过好消息是Cocos 引擎在premultiplyAlpha: true时会自动调整内置材质的混合模式大部分情况下你不用手动改。但如果你用了自定义 shader那就得自己注意了。自定义 shader 里如果写死了SRC_ALPHA在预乘模式下就会出问题。实操心得我一般会先不开premultiplyAlpha只开alpha看看效果。如果边缘没有明显黑边说明美术资源本身处理得比较干净可以不开预乘省去一堆麻烦。如果黑边明显再开预乘并统一纹理设置。这样能减少不必要的复杂度。6. 不同浏览器与嵌入场景的兼容性6.1 主流浏览器的表现差异透明背景在 Chrome、Firefox、Safari、Edge 上的表现总体一致但有几个细节差异Safari对预乘 alpha 的处理比较严格如果纹理没设对黑边会比 Chrome 更明显。另外 Safari 在 iOS 上对 canvas 的 alpha 支持一直有些小毛病建议在真机上多测。Firefox早期版本对premultipliedAlpha的 WebGL context 属性支持有 bug3.0.0 那个时期2020 年底到 2021 年初的 Firefox 版本可能会有透明失效的情况。如果遇到升级浏览器或者检查 context 属性。移动端浏览器iOS Safari 和 Android Chrome 基本没问题但一些国产浏览器的内核版本较老可能不支持某些 WebGL 特性。建议在目标机型上实测。6.2 iframe 嵌入的注意事项如果游戏是通过 iframe 嵌入的除了游戏本身透明iframe 标签也要设allowtransparencytrue虽然这个属性在 HTML5 里已经废弃但部分浏览器还认并且 iframe 的body背景要透明。更现代的做法是直接用 CSSiframe { background: transparent; border: none; }同时被嵌入页面的index.html里html和body都要透明这个前面说过了。6.3 与页面其他元素的层级关系透明背景的游戏嵌在页面里经常会遇到点击穿透的问题。因为 canvas 透明区域在视觉上是透明的但 DOM 层面它还是一个占位的元素会拦截鼠标事件。如果你希望透明区域的点击能穿透到下面的页面元素需要给 canvas 设置#GameCanvas { pointer-events: none; }但这样游戏本身的交互也会失效。所以通常的做法是游戏区域内的交互由游戏处理游戏区域外的点击穿透由外层容器控制。这个要根据具体需求来不是透明背景本身的问题但经常一起出现提前想清楚。7. 常见问题排查速查表现象可能原因排查方向背景还是白的context 没开 alpha检查game.init的alpha参数背景透明但模型发黑预乘 alpha 不匹配检查纹理 Premultiply Alpha 设置边缘一圈黑边非预乘纹理 预乘混合统一纹理和引擎的预乘设置透明区域有残留拖影clearFlags 设成了 DONT_CLEAR改成 DEPTH_ONLY某些浏览器透明失效浏览器兼容性检查 context 属性升级浏览器嵌入后透明失效外层容器不透明检查 iframe 和父级 CSS半透明物体颜色发灰混合模式不对检查自定义 shader 的 blend 设置构建后改动丢失没改构建模板用 build-templates 目录这个表是我在实际项目里踩坑总结的基本上覆盖了 90% 的透明背景问题。遇到问题先对号入座能省不少排查时间。8. 我个人的实操体会与几个小技巧最后分享几个我在这个项目里摸出来的经验都是文档里不会写的。第一先做最小验证。不要一上来就在复杂项目里改先新建一个空场景放一个立方体按上面的步骤走一遍确认透明没问题再往正式项目里迁移。这样能把引擎配置问题和项目资源问题分开排查起来快很多。第二构建模板改完后用 git 管理起来。build-templates目录是项目的一部分应该提交到版本控制。不然换台机器或者重装引擎又得重新配一遍。第三3.0.0 到 3.4 之间 API 有变化。如果你后面升级引擎game.init的配置方式可能变了application.js的结构也可能调整。升级时重点看构建模板和启动脚本这两个地方最容易出兼容问题。第四性能上不用太担心。开 alpha 通道带来的性能开销很小实测在移动端也就 1% 到 2% 的帧率差异除非你是极限性能场景否则不用为了这点开销放弃透明背景。第五多准备一套不透明的构建配置。如果同一个项目既要透明嵌入又要独立全屏运行可以准备两套构建模板用构建脚本或者手动切换。Cocos Creator 支持配置多个构建任务这个在 3.0.0 里已经可以做了。这个需求本身不复杂但 3.0.0 这个版本的资料确实少希望这篇东西能帮到同样卡在这个版本上的朋友。如果你用的是更新的版本思路一样只是文件位置和参数名可能微调对着官方文档的构建章节找一下对应位置就行。