You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 19:43:11