如何在React组件中修改WebGL Unity分辨率并保持组件尺寸不变
解决Unity WebGL嵌入React后内部分辨率修改导致组件尺寸异常的问题
核心思路
Unity内部调用Screen.SetResolution时会直接修改canvas元素的width和height属性,覆盖React组件的样式控制。要保持React组件尺寸不变,需要通过CSS强制锁定canvas的显示尺寸,同时配合react-unity-webgl的配置和事件监听适配渲染逻辑。
具体解决方案
1. 用容器包裹Unity组件并设置强制样式
给Unity组件外层添加容器控制整体尺寸,让内部canvas强制占满容器,忽略Unity修改的canvas属性:
import React, { useEffect } from "react"; import { Unity, useUnityContext } from "react-unity-webgl"; function App() { const { unityProvider, addEventListener, removeEventListener } = useUnityContext({ loaderUrl: "Build/Build.loader.js", dataUrl: "Build/Build.data", frameworkUrl: "Build/Build.framework.js", codeUrl: "Build/Build.wasm", matchWebGLToCanvasSize: false, // 关闭WebGL上下文与canvas尺寸绑定 streamingAssetsUrl: "StreamingAssets", }); // Unity加载完成后强制同步显示尺寸 function handleUnityLoaded() { const canvas = document.querySelector(".unity-canvas"); if (canvas) { canvas.style.width = "100%"; canvas.style.height = "100%"; // 通知Unity容器的实际像素尺寸,适配内部渲染 unityProvider.send("UnityRenderManager", "UpdateRenderResolution", window.innerWidth, Math.floor(window.innerWidth * 0.5625)); } } useEffect(() => { addEventListener("loaded", handleUnityLoaded); return () => removeEventListener("loaded", handleUnityLoaded); }, [addEventListener, removeEventListener]); return ( <div style={{ width: '100vw', height: '56.25vw', overflow: 'hidden', position: 'relative' }}> <Unity unityProvider={unityProvider} className="unity-canvas" style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', objectFit: 'contain' // 保持游戏画面比例,可选cover填充容器 }} /> </div> ); } export default App;
2. Unity端配合调整(关键)
让Unity开发人员修改内部分辨率逻辑,只调整渲染分辨率而非显示尺寸:
using UnityEngine; public class UnityRenderManager : MonoBehaviour { // 接收JS传递的渲染分辨率 public void UpdateRenderResolution(int width, int height) { // 设置内部渲染分辨率,不修改窗口显示尺寸 Screen.SetResolution(width, height, false); // 可选:同步UI适配 CanvasScaler canvasScaler = FindObjectOfType<CanvasScaler>(); if (canvasScaler != null) { canvasScaler.referenceResolution = new Vector2(width, height); } } }
3. 处理窗口Resize事件
添加监听确保窗口变化时同步渲染分辨率:
useEffect(() => { function handleResize() { const containerHeight = Math.floor(window.innerWidth * 0.5625); unityProvider.send("UnityRenderManager", "UpdateRenderResolution", window.innerWidth, containerHeight); // 强制canvas样式同步 const canvas = document.querySelector(".unity-canvas"); if (canvas) { canvas.style.width = "100%"; canvas.style.height = "100%"; } } window.addEventListener("resize", handleResize); return () => window.removeEventListener("resize", handleResize); }, [unityProvider]);
为什么单独设置matchWebGLToCanvasSize: false无效?
该选项仅控制WebGL上下文分辨率是否跟随canvas尺寸,但Unity的Screen.SetResolution会直接修改canvas的width和height属性(非CSS样式),浏览器会按这个属性值渲染显示尺寸,因此必须用CSS强制覆盖显示样式,同时让Unity只调整内部渲染分辨率。
内容的提问来源于stack exchange,提问作者Yvonne Cr.
相关产品推荐
相关产品推荐

