能否在React JS Web应用中集成Godot作为3D模型查看器并联动UI?
能否将Godot嵌入React作为3D模型查看器并实现UI联动?
完全可以,你可以将Godot导出为WebAssembly(Wasm)版本,嵌入到React应用中作为3D查看器,并且通过跨上下文消息通信实现Godot与React UI的双向交互。以下是具体实现步骤:
1. 将Godot项目导出为Web版本
Godot 3.x和4.x均支持导出HTML5(Wasm)格式,步骤如下:
- 打开你的Godot 3D项目,配置好相机操控逻辑(比如给
Camera3D添加拖拽、缩放控制,或自定义视角交互) - 点击
Project > Export > Add...选择HTML5导出模板 - 在导出设置中:
- 关闭不必要的模块(如音频、网络,若无需使用)以减小包体积
- 启用
Export as Single File(可选,将所有资源打包为单个HTML文件) - 切换为
Release模式,关闭调试功能优化性能
- 导出后得到包含
.html、.js、.wasm的文件包,将其放在React项目的public目录下(或部署到同域名的静态资源目录)
2. 在React中嵌入Godot视图
有两种主流嵌入方式,根据需求选择:
方式一:iframe嵌入(快速集成)
通过iframe直接加载Godot导出的HTML文件,适合快速搭建原型:
import { useEffect, useRef, useState } from 'react'; const Godot3DViewer = () => { const iframeRef = useRef(null); const [cameraPose, setCameraPose] = useState({ position: {}, rotation: {} }); // 监听Godot发来的消息 useEffect(() => { const handleMessage = (e) => { // 生产环境务必限制消息来源origin,避免安全风险 const parsedData = JSON.parse(e.data); if (parsedData?.type === 'camera_updated') { setCameraPose({ position: parsedData.position, rotation: parsedData.rotation }); // 这里可触发React UI的其他更新,比如同步视角参数到表单 } }; window.addEventListener('message', handleMessage); return () => window.removeEventListener('message', handleMessage); }, []); // 从React发送指令到Godot(示例:控制模型旋转) const rotateModel = () => { iframeRef.current?.contentWindow.postMessage( JSON.stringify({ type: 'rotate_model', angle: 45 }), window.location.origin // 生产环境指定具体origin ); }; return ( <div className="godot-viewer-container"> <iframe ref={iframeRef} src="/godot-export/index.html" // 指向public目录下的Godot导出文件 width="100%" height="700px" frameBorder="0" title="Godot 3D Viewer" /> {/* React UI联动示例:展示Godot相机状态 */} <div className="viewer-controls"> <h3>当前视角参数</h3> <p>位置:X={cameraPose.position.x || 0} Y={cameraPose.position.y || 0} Z={cameraPose.position.z || 0}</p> <p>旋转:X={cameraPose.rotation.x || 0}° Y={cameraPose.rotation.y || 0}° Z={cameraPose.rotation.z || 0}°</p> <button onClick={rotateModel}>旋转模型45°</button> </div> </div> ); }; export default Godot3DViewer;
方式二:直接集成Godot JS模块(深度融合)
如果需要更无缝的集成(比如共享DOM上下文),可以将Godot的JS库直接导入React项目:
import { useEffect, useRef } from 'react'; const GodotIntegratedViewer = () => { const containerRef = useRef(null); useEffect(() => { if (!containerRef.current) return; // 加载Godot JS模块 const script = document.createElement('script'); script.src = '/assets/godot.js'; script.onload = () => { // 初始化Godot实例 const engine = new GodotEngine(); engine.startGame({ canvas: containerRef.current, executable: '/assets/godot.wasm', args: [], canvasResizePolicy: 2 // 自适应容器大小 }); // 监听Godot消息 window.addEventListener('message', (e) => { const parsedData = JSON.parse(e.data); if (parsedData.type === 'model_selected') { // 更新React UI状态 console.log('选中模型:', parsedData.modelId); } }); }; document.body.appendChild(script); return () => { document.body.removeChild(script); // 销毁Godot实例 window.GodotEngine?.stopGame(); }; }, []); return <div ref={containerRef} style={{ width: '100%', height: '700px' }} />; }; export default GodotIntegratedViewer;
3. 实现Godot与React的双向通信
通过postMessage和Godot的JavaScript类实现跨上下文通信:
Godot发送消息到React(GDScript示例)
当用户调整视角或操作模型时,发送数据到React:
extends Camera3D var last_transform: Transform3D func _process(delta): # 仅在相机变换时发送更新,避免频繁通信 if global_transform != last_transform: last_transform = global_transform var cameraData = { "type": "camera_updated", "position": { "x": global_position.x, "y": global_position.y, "z": global_position.z }, "rotation": { "x": global_rotation_degrees.x, "y": global_rotation_degrees.y, "z": global_rotation_degrees.z } } JavaScript.call("window.postMessage", JSON.stringify(cameraData), "*")
Godot接收React的消息(GDScript示例)
监听来自React的指令并执行对应操作:
extends Node3D func _ready(): # 监听window的message事件 JavaScript.connect("message", self, "_on_react_message") func _on_react_message(event): var data = JSON.parse_string(event.data) match data.type: "rotate_model": $Model.rotate_y(deg_to_rad(data.angle)) "zoom_camera": $Camera3D.fov = data.fov
注意事项
- 安全问题:生产环境中务必限制
postMessage的targetOrigin,避免跨域消息泄露 - 性能优化:Godot Web版本需优化模型面数、纹理压缩,关闭不必要的渲染特性,避免占用过多浏览器资源
- 资源路径:确保Godot导出的资源文件与React应用在同一域名下,避免跨域加载问题
内容的提问来源于stack exchange,提问作者Jonathan A
相关产品推荐
相关产品推荐

