WEBGL · WASM EDITION
完全开放的沙盒地图,没有赛道限制。超真实刚体物理引擎驱动 —— 翻车、飞跃、360° 空翻全部真实模拟。 跑车、越野、肌肉车随你切换,纯 WebGL + WebAssembly 渲染,无需下载客户端。
无赛道限制,全地图任你狂飙,想怎么开就怎么开。
翻车、飞跃、360° 空翻全模拟,刚体碰撞逐帧解算。
跑车、越野车、肌肉车自由切换,性能手感各不相同。
无需下载,WebAssembly 提速,低配电脑也能流畅运行。
学习 WebGL / 3D 游戏引擎与物理引擎的优秀案例。
| 文件 | 类型 | 作用 |
|---|---|---|
| index.html | HTML | 游戏入口文件,加载 Unity WebGL 容器 |
| game.json | JSON | Unity 导出的资源配置清单 |
| *.unityweb | Binary | Unity 编译的 WebAssembly 模块和资源包 |
| style.css | CSS | 页面样式表 |
| js/*.js | JavaScript | Unity 加载器和自定义脚本 |
通过 UnityLoader 实例化容器,并监听加载进度回调。
<script src="js/UnityLoader.js"></script> <script> UnityLoader.instantiate("gameContainer", "game.json", { onProgress: (progress) => { console.log(`加载进度: ${Math.round(progress*100)}%`); } }); </script>
JS 通过 SendMessage 调用 C# 方法,C# 通过 DllImport 回传数据。
// JavaScript 调用 C# 方法 gameInstance.SendMessage('CarController', 'ApplyBrake', 'true'); // C# 调用 JavaScript(需用 [DllImport] 声明) window.receiveFromUnity = (data) => { console.log("Unity消息:", data); };
手动释放 WASM 堆内存,分段加载 code / data / framework 资源包。
// 手动释放 Unity 内存 gameInstance.Module._free(bufferPtr); // 分段加载资源 UnityLoader.instantiate("gameContainer", { dataUrl: "data.unityweb", streamingAssetsUrl: "StreamingAssets", codeUrl: "asmCode.unityweb", frameworkUrl: "asmFramework.unityweb", });
键盘事件映射到游戏引擎;特技判定由引擎回传加分。
// C# 端特技判定 public class StuntManager : MonoBehaviour { [DllImport("__Internal")] private static extern void AddScore(int points); void Complete360() { AddScore(500); } } // JS 端接收加分 window.AddScore = (points) => { const el = document.getElementById('score'); el.textContent = parseInt(el.textContent) + points; };
利用虚拟文件系统写入自定义模型,或通过 WebSocket 同步玩家位置。
// 动态加载 MOD 车辆模型 function loadModCar(modelUrl) { fetch(modelUrl) .then(res => res.arrayBuffer()) .then(data => { gameInstance.Module.FS_writeFile( '/mods/car.fbx', new Uint8Array(data)); gameInstance.SendMessage('ModLoader', 'LoadCar', '/mods/car.fbx'); }); }
读取帧间隔计算 FPS,接管引擎的标准输出流做日志转发。
// 帧率监控 setInterval(() => { const fps = 1 / gameInstance.Module.unityPerformance.nowFrameDelta; console.log(`当前FPS: ${fps.toFixed(1)}`); }, 1000); // 激活引擎控制台输出 gameInstance.Module.print = (t) => console.debug('[Unity]', t); gameInstance.Module.printErr = (t) => console.error('[Unity]', t);
Unity WebGL 版本通过 UnityLoader 加载编译后的 WASM 模块、game.json 管理资源依赖,并用跨语言调用驱动游戏逻辑。 下列为原始工程的关键实现片段。
<script src="js/UnityLoader.js"></script> <script> UnityLoader.instantiate("gameContainer", "game.json", { onProgress: (progress) => console.log(`加载进度: ${Math.round(progress*100)}%`) }); </script>
gameInstance.SendMessage('CarController', 'ApplyBrake', 'true'); window.receiveFromUnity = (data) => console.log("Unity消息:", data);
document.addEventListener('keydown', (e) => { const keyState = e.type === 'keydown' ? 1 : 0; switch(e.key) { case 'ArrowUp': gameInstance.SendMessage('Car', 'SetThrottle', keyState); break; case 'ArrowLeft': gameInstance.SendMessage('Car', 'SetSteering', -keyState); break; } });
// C# 端 public class StuntManager : MonoBehaviour { [DllImport("__Internal")] private static extern void AddScore(int points); void Complete360() { AddScore(500); } } // JS 端 window.AddScore = (points) => { document.getElementById('score').textContent = parseInt(document.getElementById('score').textContent) + points; };
gameInstance.Module._free(bufferPtr); UnityLoader.instantiate("gameContainer", { dataUrl: "data.unityweb", streamingAssetsUrl: "StreamingAssets", codeUrl: "asmCode.unityweb", frameworkUrl: "asmFramework.unityweb", });
function loadModCar(modelUrl) { fetch(modelUrl).then(r => r.arrayBuffer()).then(data => { gameInstance.Module.FS_writeFile('/mods/car.fbx', new Uint8Array(data)); gameInstance.SendMessage('ModLoader', 'LoadCar', '/mods/car.fbx'); }); } const ws = new WebSocket('wss://game-server.example.com'); ws.onmessage = (event) => { const d = JSON.parse(event.data); gameInstance.SendMessage('Network', 'UpdatePlayerPosition', `${d.x},${d.y},${d.z}`); };
setInterval(() => {
const fps = 1 / gameInstance.Module.unityPerformance.nowFrameDelta;
console.log(`当前FPS: ${fps.toFixed(1)}`);
}, 1000);
gameInstance.Module.print = (t) => console.debug('[Unity]', t);
gameInstance.Module.printErr = (t) => console.error('[Unity]', t);