Unity WebGL构建中无法设置WebcamTexture分辨率求助
Unity WebGL WebCamTexture 分辨率设置无效(始终480×640)解决方案
问题原因
Unity WebGL平台下,WebCamTexture的requestedWidth/requestedHeight参数无法直接生效,本质是因为WebGL依赖浏览器的getUserMedia API,而浏览器仅允许选择摄像头硬件支持的固定分辨率档位,Unity的封装逻辑在WebGL上对自定义分辨率的处理存在限制,导致默认 fallback 到480×640。
解决步骤
1. 获取浏览器支持的摄像头分辨率档位
通过JavaScript插件调用浏览器原生API,获取当前摄像头支持的所有分辨率,筛选出最接近16:9的档位。
创建Plugins/WebGL/CameraResolution.jslib文件,放入以下代码:
mergeInto(LibraryManager.library, { GetSupportedResolutions: function() { navigator.mediaDevices.getUserMedia({ video: true }) .then(stream => { const track = stream.getVideoTracks()[0]; const capabilities = track.getCapabilities(); const resolutions = []; // 遍历所有支持的宽高组合 if (capabilities.width?.values && capabilities.height?.values) { for (let i = 0; i < capabilities.width.values.length; i++) { resolutions.push(`${capabilities.width.values[i]}x${capabilities.height.values[i]}`); } } // 关闭临时流 stream.getTracks().forEach(track => track.stop()); // 将结果传递给Unity sendMessage('CameraController', 'OnResolutionsReceived', JSON.stringify(resolutions)); }) .catch(err => { console.error('获取分辨率失败:', err); sendMessage('CameraController', 'OnResolutionsReceived', '[]'); }); } });
2. 修改Unity C#代码适配WebGL
更新摄像头初始化逻辑,优先使用浏览器支持的16:9分辨率,若无法匹配则用RenderTexture做缩放适配:
using UnityEngine; using System.Collections.Generic; using System.Runtime.InteropServices; public class CameraController : MonoBehaviour { private WebCamTexture _camTexture; public Renderer _displayRenderer; private int _currentCamIndex = 0; [DllImport("__Internal")] private static extern void GetSupportedResolutions(); // 接收JS传递的分辨率列表 public void OnResolutionsReceived(string jsonResolutions) { var resList = new List<string>(JsonUtility.FromJson<string[]>(jsonResolutions)); var targetRatio = 16f / 9f; Vector2Int bestRes = Vector2Int.zero; float closestRatioDiff = float.MaxValue; foreach (var res in resList) { var parts = res.Split('x'); if (parts.Length != 2) continue; if (int.TryParse(parts[0], out int w) && int.TryParse(parts[1], out int h)) { float currentRatio = (float)w / h; float diff = Mathf.Abs(currentRatio - targetRatio); // 优先选择比例最接近且分辨率较高的 if (diff < closestRatioDiff || (diff == closestRatioDiff && w > bestRes.x)) { closestRatioDiff = diff; bestRes = new Vector2Int(w, h); } } } // 启动摄像头,找不到匹配分辨率则 fallback 到1280x720 StartCoroutine(InitCamera(bestRes.x > 0 ? bestRes.x : 1280, bestRes.y > 0 ? bestRes.y : 720)); } private IEnumerator InitCamera(int targetWidth, int targetHeight) { // 清理旧的摄像头资源 if (_camTexture != null) { _displayRenderer.material.mainTexture = null; _camTexture.Stop(); _camTexture = null; yield return null; } // 初始化摄像头 var device = WebCamTexture.devices[_currentCamIndex]; _camTexture = new WebCamTexture(device.name, targetWidth, targetHeight, 24); _displayRenderer.material.mainTexture = _camTexture; _camTexture.Play(); yield return new WaitForEndOfFrame(); // 检查实际分辨率是否符合16:9,不符合则用RenderTexture缩放适配 if (Mathf.Abs((float)_camTexture.width / _camTexture.height - 16f/9f) > 0.01f) { var rtWidth = Mathf.RoundToInt(_camTexture.height * 16f/9f); var renderTexture = new RenderTexture(rtWidth, _camTexture.height, 0); _displayRenderer.material.mainTexture = renderTexture; StartCoroutine(BlitCameraToRT(_camTexture, renderTexture)); } } // 将摄像头画面实时 blit 到RenderTexture做适配 private IEnumerator BlitCameraToRT(WebCamTexture source, RenderTexture dest) { while (source.isPlaying) { Graphics.Blit(source, dest); yield return null; } Destroy(dest); } private void Start() { #if UNITY_WEBGL && !UNITY_EDITOR // WebGL平台下调用JS获取分辨率 GetSupportedResolutions(); #else // 其他平台沿用原有逻辑 StartCoroutine(InitCamera(1024, 576)); #endif } }
3. 额外注意事项
- WebGL平台需要HTTPS环境才能访问摄像头(本地
localhost调试除外)。 - 部分浏览器可能限制摄像头分辨率,需确保用户授权摄像头权限。
- 若存在画面镜像问题,可通过设置
_displayRenderer.material.mainTextureScale = new Vector2(-1, 1)修正。
内容的提问来源于stack exchange,提问作者Raphael Huot
相关产品推荐
相关产品推荐

