React JS嵌入Unity WebGL时WASM文件magic header报错问题
问题原因
你遇到的magic header not detected报错是因为React脚手架默认的webpack配置没有适配WASM二进制文件的解析规则,你直接在src目录下import .wasm文件时,webpack用默认的file-loader解析二进制内容导致解析失败。
原生手动修复方案
步骤1:调整Unity构建资源的存放位置
把你整个Unity构建出来的BuildWebGl3文件夹、配套的TemplateData文件夹全部放到React项目的public目录下,不要放在src目录中,这样不需要import资源,直接用公共路径引用即可,绕开webpack的资源解析逻辑。
步骤2:修改组件代码
删除所有Unity资源的import语句,恢复你之前注释的初始化逻辑,修改后的完整代码如下:
import React, {useEffect} from "react"; function Component1() { useEffect(() => { const buildUrl = "/BuildWebGl3/Build"; const loaderUrl = buildUrl + "/BuildWebGl3.loader.js"; const config = { dataUrl: buildUrl + "/BuildWebGl3.data", frameworkUrl: buildUrl + "/BuildWebGl3.framework.js", codeUrl: buildUrl + "/BuildWebGl3.wasm", streamingAssetsUrl: "StreamingAssets", companyName: "DefaultCompany", productName: "My project (1)", productVersion: "1.0", }; const container = document.querySelector("#unity-container"); const canvas = document.querySelector("#unity-canvas"); const loadingBar = document.querySelector("#unity-loading-bar"); const progressBarFull = document.querySelector("#unity-progress-bar-full"); const fullscreenButton = document.querySelector("#unity-fullscreen-button"); const mobileWarning = document.querySelector("#unity-mobile-warning"); if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) { container.className = "unity-mobile"; config.devicePixelRatio = 1; mobileWarning.style.display = "block"; setTimeout(() => { mobileWarning.style.display = "none"; }, 5000); } else { canvas.style.width = "960px"; canvas.style.height = "600px"; } loadingBar.style.display = "block"; const script = document.createElement("script"); script.src = loaderUrl; script.onload = () => { createUnityInstance(canvas, config, (progress) => { progressBarFull.style.width = 100 * progress + "%"; }).then((unityInstance) => { loadingBar.style.display = "none"; fullscreenButton.onclick = () => { unityInstance.SetFullscreen(1); }; }).catch((message) => { alert(message); }); }; document.body.appendChild(script); script.async = true; return () => { document.body.removeChild(script); } }, []); return( <div> <div id="unity-container" className="unity-desktop"> <canvas id="unity-canvas"></canvas> <div id="unity-loading-bar"> <div id="unity-logo"></div> <div id="unity-progress-bar-empty"> <div id="unity-progress-bar-full"></div> </div> </div> <div id="unity-mobile-warning"> WebGL builds are not supported on mobile devices. </div> <div id="unity-footer"> <div id="unity-webgl-logo"></div> <div id="unity-fullscreen-button"></div> <div id="unity-build-title">My project (1)</div> </div> </div> </div> ); } export default Component1;
步骤3:引入Unity配套样式
打开React项目的public/index.html,在head标签内添加Unity的样式引用:
<link rel="stylesheet" href="/TemplateData/style.css"> <link rel="shortcut icon" href="/TemplateData/favicon.ico">
更简便的实现方案
直接使用封装好的react-unity-webgl库,省去手动处理加载逻辑、适配webpack的步骤:
- 安装依赖:
npm install react-unity-webgl - 简化后的组件代码:
import { Unity, useUnityContext } from "react-unity-webgl"; function Component1() { const { unityProvider, loadingProgression } = useUnityContext({ loaderUrl: "/BuildWebGl3/Build/BuildWebGl3.loader.js", dataUrl: "/BuildWebGl3/Build/BuildWebGl3.data", frameworkUrl: "/BuildWebGl3/Build/BuildWebGl3.framework.js", codeUrl: "/BuildWebGl3/Build/BuildWebGl3.wasm", }); return ( <> {loadingProgression < 1 && <div>加载进度:{Math.round(loadingProgression * 100)}%</div>} <Unity unityProvider={unityProvider} style={{ width: 960, height: 600 }} /> </> ); }
部署注意事项
如果项目部署在域名的子路径下,需要把所有Unity资源的路径前加上对应的子路径前缀,比如部署在/mygame路径下,资源路径就改成/mygame/BuildWebGl3/xxx。
内容的提问来源于stack exchange,提问作者YMELO
相关产品推荐
相关产品推荐

