Unity WebGL App在Bootstrap模态框隐藏时出现"Screen position out of view frustum"错误的解决方法
嘿,这个问题我太熟了!之前帮好几个做Unity WebGL嵌入Bootstrap模态框的开发者解决过,本质是当模态框被display:none隐藏时,Unity的容器尺寸会被压缩到0×0,这时候相机的视锥体计算就会彻底混乱,抛出那个烦人的"Screen position out of view frustum"错误。下面给你几个实用的解决方案,按优先级排序:
方案1:隐藏时暂停渲染,显示时恢复(最推荐)
这是最合理的做法——既然模态框看不见,干脆暂停Unity的渲染,既解决错误又节省浏览器性能。
第一步,在网页端监听Bootstrap模态框的显示/隐藏事件,同时保存Unity实例的引用:
// 假设你的模态框ID是unityModal const unityModal = document.getElementById('unityModal'); let unityInstance = null; // Unity加载完成后保存实例(用Unity默认的Progress回调) function UnityProgress(instance, progress) { if (progress === 1) { window.unityInstance = instance; } } // 模态框隐藏时暂停渲染 unityModal.addEventListener('hidden.bs.modal', () => { if (window.unityInstance) { // 给Unity发送消息,让内部暂停渲染 window.unityInstance.SendMessage('GameManager', 'ToggleRendering', false); // 也可以直接调用WebGL API暂停整个实例 // window.unityInstance.Pause(); } }); // 模态框显示时恢复渲染并更新尺寸 unityModal.addEventListener('shown.bs.modal', () => { if (window.unityInstance) { window.unityInstance.SendMessage('GameManager', 'ToggleRendering', true); // 恢复实例 // window.unityInstance.Resume(); // 强制Unity更新容器尺寸,避免显示异常 window.unityInstance.Module.resize(); } });第二步,在Unity里写一个简单的
GameManager脚本,接收网页发来的消息控制渲染:using UnityEngine; public class GameManager : MonoBehaviour { public Camera mainCamera; // 如果有多个相机,可以用数组批量控制 // public Camera[] allCameras; public void ToggleRendering(bool enable) { mainCamera.enabled = enable; // 批量控制多个相机的写法 // foreach(var cam in allCameras) cam.enabled = enable; // 也可以配合时间缩放暂停游戏逻辑(可选) // Time.timeScale = enable ? 1 : 0; } }
方案2:替换display:none,用其他方式隐藏模态框
如果不想暂停Unity渲染,可以修改Bootstrap模态框的隐藏逻辑,让容器保持原有尺寸,只是移出可视区域:
先自定义一个隐藏样式:
.modal.hidden-offscreen { display: block !important; visibility: hidden; position: absolute; top: -9999px; left: -9999px; }然后修改模态框的显示/隐藏逻辑,不用Bootstrap默认的
hide()方法,而是切换自定义类:const unityModal = document.getElementById('unityModal'); // 自定义隐藏方法 function hideUnityModal() { unityModal.classList.add('hidden-offscreen'); } // 自定义显示方法 function showUnityModal() { unityModal.classList.remove('hidden-offscreen'); // 显示后强制更新Unity容器尺寸 if (window.unityInstance) { window.unityInstance.Module.resize(); } }
这种方法的缺点是Unity依然在后台渲染,会占用额外资源,适合必须保持游戏运行的场景。
方案3:Unity内部修复视锥体异常
如果上面的方法都不适用,可以在Unity端监听相机状态,当检测到视锥体异常时强制修正参数:
using UnityEngine; public class CameraFrustumFix : MonoBehaviour { private Camera _cam; private float _originalAspect; private float _originalFov; void Start() { _cam = GetComponent<Camera>(); _originalAspect = _cam.aspect; _originalFov = _cam.fieldOfView; } void Update() { // 检测宽高比是否异常(比如容器尺寸为0导致的NaN或极小值) if (float.IsNaN(_cam.aspect) || _cam.aspect <= 0.001f) { // 恢复初始的宽高比和视野参数 _cam.aspect = _originalAspect; _cam.fieldOfView = _originalFov; } } }
这个方法属于“治标”,只能抑制错误日志,还是推荐结合方案1一起使用。
内容的提问来源于stack exchange,提问作者Patrick Münster
相关产品推荐
相关产品推荐

