Unity WebGL 开发实战 🔥 游戏/3D
从 Unity 开发到 WebGL 导出,从性能优化到前端集成,掌握 Unity Web 开发全流程
学习时长:约 20 小时 | 前置:C# 基础、Unity 基础 | 产出:Unity WebGL 项目
一、Unity WebGL 概述
什么是 Unity WebGL?
Unity WebGL 是 Unity 平台的 Web 发布目标,通过 WebAssembly 和 WebGL 在浏览器中运行 Unity 内容。
Unity 编辑器
→
IL2CPP/WASM
→
WebGL 渲染
→
浏览器运行
| 特性 | 说明 |
| 跨平台 | 支持所有现代浏览器 |
| 高性能 | WebAssembly 接近原生性能 |
| 3D 能力 | 完整 Unity 3D 功能 |
| 交互 | 支持键盘、鼠标、触摸、游戏手柄 |
| 音频 | Web Audio API 集成 |
二、Unity 项目设置
2.1 构建配置
Player Settings
- Compression Format:Gzip 或 Brotli(推荐 Brotli,压缩率更高)
- WebGL Template:Default 或 Minimal
- Exception Support:None(发布时关闭,减小体积)
- Data Caching:开启,缓存数据避免重复下载
2.2 构建设置
// Unity 菜单:File → Build Settings → WebGL
// 关键设置:
// 1. Compression Format: Brotli
// 2. Name: webgl
// 3. Enable Exceptions: None
// 4. Data Caching: Enabled
// 5. Debugging: Disabled (发布时)
三、WebGL 前端集成
3.1 基础加载
// index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Unity WebGL</title>
<script src="Build/UnityLoader.js"></script>
</head>
<body>
<div id="gameContainer" style="width: 960px; height: 600px; margin: auto"></div>
<script>
var gameInstance = UnityLoader.instantiate(
"gameContainer",
"Build/webgl.json",
{ onProgress: unityProgress }
);
function unityProgress(gameInstance, progress) {
if (!gameInstance.Module) return;
const loader = document.querySelector("#loader");
if (progress === 1) loader.style.display = "none";
}
</script>
</body>
</html>
3.2 新版 Unity (2020+) 加载
// 新版 Unity 使用 createUnityInstance
var buildUrl = "Build";
var loaderUrl = buildUrl + "/webgl.loader.js";
var config = {
dataUrl: buildUrl + "/webgl.data.br",
frameworkUrl: buildUrl + "/webgl.framework.js.br",
codeUrl: buildUrl + "/webgl.wasm.br",
streamingAssetsUrl: "StreamingAssets",
companyName: "YourCompany",
productName: "YourGame",
productVersion: "1.0"
};
var container = document.querySelector("#unity-container");
var canvas = document.querySelector("#unity-canvas");
var loadingBar = document.querySelector("#unity-loading-bar");
var progressBarFull = document.querySelector("#unity-progress-bar-full");
var fullscreenButton = document.querySelector("#unity-fullscreen-button";
// 加载
createUnityInstance(canvas, config, (progress) => {
progressBarFull.style.width = 100 * progress + "%";
}).then((unityInstance) => {
loadingBar.style.display = "none";
fullscreenButton.onclick = () => unityInstance.SetFullscreen(1);
}).catch((message) => alert(message));
四、Unity 与 JavaScript 通信
4.1 Unity → JavaScript
// Unity C# 代码
using UnityEngine;
using System.Runtime.InteropServices;
public class JSBridge : MonoBehaviour {
[DllImport("__Internal")]
private static extern void SendMessageToJS(string msg);
public void OnGameOver(int score) {
SendMessageToJSON(JsonUtility.ToJson(new GameResult { score = score }));
}
}
// JavaScript 接收
function SendMessageToJSON(json) {
const data = JSON.parse(json);
console.log('游戏结束,得分:' + data.score);
}
4.2 JavaScript → Unity
// JavaScript 调用 Unity
function SendToUnity(methodName, param) {
if (typeof param === 'object') {
param = JSON.stringify(param);
}
gameInstance.SendMessage('GameManager', methodName, param);
}
// 调用示例
SendToUnity('SetLevel', '3');
SendToUnity('SetConfig', { volume: 0.8, quality: 'high' });
// Unity C# 接收
public void SetLevel(string level) {
SceneManager.LoadScene("Level" + level);
}
public void SetConfig(string json) {
var config = JsonUtility.FromJson<GameConfig>(json);
AudioListener.volume = config.volume;
}
五、性能优化
优化策略
| 策略 | 说明 |
| 压缩 | Brotli 压缩,体积减少 60-80% |
| 资源优化 | 纹理压缩、模型减面、音频压缩 |
| 代码裁剪 | Strip Engine Code,移除未使用模块 |
| AssetBundle | 按需加载,减少首包体积 |
| LOD | 多层次细节,远距离用低模 |
| 遮挡剔除 | 不渲染被遮挡的物体 |
| 对象池 | 复用对象,减少 GC |
5.1 资源优化
// 纹理设置
// Max Size: 1024 或 512
// Compression: ASTC 或 ETC2
// Generate Mip Maps: 开启
// 模型设置
// Mesh Compression: Medium
// Optimize Mesh: 开启
// Generate Colliders: 关闭(除非需要)
六、React/Vue 集成
6.1 React 集成
// UnityCanvas.jsx
import { useEffect, useRef } from 'react';
import UnityLoader from 'react-unity-webgl';
export default function UnityCanvas() {
const unityContext = new UnityLoader({
loaderUrl: "Build/webgl.loader.js",
dataUrl: "Build/webgl.data.br",
frameworkUrl: "Build/webgl.framework.js.br",
codeUrl: "Build/webgl.wasm.br"
});
useEffect(() => {
unityContext.on("ready", () => {
// Unity 加载完成
});
}, []);
return (
<UnityContextProvider unityContext={unityContext}>
<canvas ref={canvasRef} />
</UnityContextProvider>
);
}
七、部署与运维
部署配置
// Nginx 配置
server {
listen 80;
server_name game.example.com;
root /var/www/unity-webgl;
// 开启 gzip
gzip on;
gzip_types application/javascript application/wasm application/octet-stream;
// 缓存
location ~* \.(wasm|data|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
// 跨域
add_header Cross-Origin-Opener-Policy same-origin;
add_header Cross-Origin-Embedder-Policy require-corp;
}
八、面试高频问题
Q1:Unity WebGL 和 Three.js 如何选择?
查看答案 ▼
| 维度 | Unity WebGL | Three.js |
| 学习成本 | 高(需学 Unity + C#) | 低(纯 JS) |
| 3D 能力 | 完整(物理、动画、AI) | 基础(需自己实现) |
| 性能 | WebAssembly,接近原生 | WebGL,依赖 JS |
| 体积 | 大(几 MB 到几十 MB) | 小(几百 KB) |
| 适用场景 | 游戏、复杂 3D | 展示、简单 3D |
Q2:Unity WebGL 首屏加载慢怎么优化?
查看答案 ▼
- 使用 Brotli 压缩
- 启用 Data Caching
- 使用 AssetBundle 按需加载
- 减少首场景资源
- 显示加载进度条
- 使用 Loading 场景预加载