Unity WebGL 全屏与自适应踩坑实录:为什么你点两次才全屏?
在 Windows / Editor 环境里,我们通常会这样控制全屏:
Screen.fullScreen = !Screen.fullScreen; 但当项目切到 WebGL 后,就会遇到各种奇怪问题:
- 第一次点击没反应
- 有时需要点两次才能全屏
- 偶尔直接
abort(-1) - 不同浏览器行为还不一致
很多人第一反应是“是不是 Unity 的 bug”,但其实原因只有一个:WebGL 的全屏是浏览器行为,而不是 Unity 行为。
一、为什么 WebGL 下不能直接用 Screen.fullScreen?
浏览器对“进入全屏”有严格限制:
- 必须由用户手势触发(点击 / 按键)
- 不能在任意时机调用
- 不允许 Unity 在后台随意请求全屏
Screen.fullScreen 在 WebGL 中只是一次尝试性的请求,浏览器有权拒绝它,这就造成了各种“不稳定现象”。
二、正确做法:使用 Unity 官方的 WebGL 全屏接口
WebGL 环境下,请只使用 gameInstance.SetFullscreen(1)。这是 Unity 官方提供的 WebGL 全屏接口,不是 Hack,也不是私有 API。
三、整体实现思路
Unity UI Button 点击(用户手势) ↓ C# 调用 JavaScript(DllImport) ↓ JS 调用 gameInstance.SetFullscreen(1 / 0) 只要保证调用链路来自真实点击事件,浏览器就不会拦截。
四、创建 WebGL 插件(.jslib)
文件路径
Assets/Plugins/WebGL/Fullscreen.jslib .jslib 的作用是:从 Unity C# 调用 JavaScript 代码
Fullscreen.jslib 内容
mergeInto(LibraryManager.library, { // 进入全屏 WebGL_SetFullscreen: function () { // gameInstance 是 Unity WebGL 导出时自动生成的全局对象 if (typeof gameInstance === 「undefined」 || !gameInstance) { console.error(「gameInstance not ready」); return; } // Unity 官方推荐的 WebGL 全屏方式 // 参数:1 = 全屏,0 = 退出全屏 gameInstance.SetFullscreen(1); }, // 退出全屏 WebGL_SetMixscreen: function () { if (typeof gameInstance === 「undefined」 || !gameInstance) { console.error(「gameInstance not ready」); return; } gameInstance.SetFullscreen(0); }, }); 注意事项:
- 不要自己调用
requestFullscreen - 不要操作 DOM 或 canvas
- Unity 已经帮你处理好了浏览器兼容问题
五、Unity C# 脚本
下面是我项目里实际使用的脚本,支持 Editor / WebGL 双环境。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; #if UNITY_WEBGL && !UNITY_EDITOR using System.Runtime.InteropServices; #endif public class SceneUtilityButtons : MonoBehaviour { #if UNITY_WEBGL && !UNITY_EDITOR // 当前是否为全屏状态 private bool state = false; // 声明 jslib 中的方法 [DllImport(「__Internal」)] private static extern void WebGL_SetFullscreen(); [DllImport(「__Internal」)] private static extern void WebGL_SetMixscreen(); #endif // 直接绑定到 Unity Button 的 OnClick public void OnClickFullscreen() { #if UNITY_WEBGL && !UNITY_EDITOR // WebGL 环境下:调用 JS 中的全屏接口 if (!state) WebGL_SetFullscreen(); else WebGL_SetMixscreen(); state = !state; #else // 非 WebGL(Editor / PC / Mobile) Screen.fullScreen = !Screen.fullScreen; #endif } } 使用方式:在 Button 里绑定 OnClickFullscreen()即可。
六、Canvas 自适应问题:很多人其实卡在锚点
即使你已经正确设置了:
Canvas → UI Scale Mode = Scale With Screen Size- Reference Resolution / Match 配置正确
在 WebGL 下仍然可能出现:
- UI 被遮住
- 全屏前后布局错乱
- 非全屏状态下显示异常
90% 的情况不是 Canvas,而是锚点没设置对。
七、常见 UI 锚点正确设置方式
背景 / 根 Panel
- 锚点:
Stretch(0,0 → 1,1) - Left / Right / Top / Bottom 全部为
0
这是最容易忽视、但最重要的一步。
顶部 UI(Logo、全屏按钮)
- 锚点贴 Top
- 不要使用 Center 锚点
- 不要靠手调 Y 值硬对齐
底部 UI(提示文字、说明信息)
- 锚点贴 Bottom
- 保证在不同分辨率下始终贴底
八、HTML 层面:越简单越稳定
最终我的 HTML 只保留:
width: 100vw; height: 100vh; 没有额外 resize 逻辑,也没有 JS 强行缩放。
UI 自适应交给 Unity,浏览器只负责显示。
九、总结
WebGL 全屏三条结论:
- 不推荐
Screen.fullScreen - 不要直接调用浏览器全屏 API
- 使用
gameInstance.SetFullscreen
UI 显示问题排查顺序:
- Canvas 设置
- UI 锚点
- 最后才考虑 HTML / JS
WebGL 的坑并不在“技术有多复杂”,而在于它不是桌面程序的思维方式。
顺着 Unity 官方的规则来,很多看起来很玄学的问题,其实一次就能解决。