{
  "schemaVersion": "0.11.0",
  "canonical": "https://www.pystone.net/notes/unity3d-webgl-framework-panorama/",
  "atlas": "https://www.pystone.net/?node=unity3d-webgl-framework-panorama#knowledge-atlas",
  "markdown": "https://www.pystone.net/notes/unity3d-webgl-framework-panorama.md",
  "context": "https://www.pystone.net/notes/unity3d-webgl-framework-panorama.context.json",
  "knowledgeVersion": "224c990773de.5fa8af6e39fa",
  "build": {
    "siteCommit": "224c990773de166d23a886306577dd90379529ce",
    "notesCommit": "5fa8af6e39fa3891d1b9b4832bfa6c4e0ecaaf0a",
    "builtAt": "1970-01-01T00:00:00.000Z",
    "version": "224c990773de.5fa8af6e39fa"
  },
  "id": "note:unity3d-webgl-framework-panorama",
  "slug": "unity3d-webgl-framework-panorama",
  "title": "Unity3D WebGL 框架全景",
  "type": "note",
  "visibility": "public",
  "idStability": "rename-stable",
  "author": {
    "name": "Perrin Yong",
    "profile": "https://www.pystone.net/profile/"
  },
  "publisher": {
    "name": "Perrin Yong",
    "profile": "https://www.pystone.net/profile/"
  },
  "aliases": [],
  "summary": "Unity3D WebGL 框架全景 !Web 平台与 WebGL 运行栈",
  "contentRole": "unspecified",
  "isMoc": false,
  "mocRecognition": "none",
  "generated": false,
  "attribution": "unspecified",
  "domain": "10-计算机、信息技术与工程",
  "tags": [],
  "mocs": [],
  "contentHash": "c581db96a2d7f796879b07cd0f3114b0f530c194fbfd18d389d4ed9c37da0ea9",
  "assets": [
    {
      "reference": "assets/web-platform-stack.png",
      "url": "/media/d2801687418797f17545.png",
      "mediaType": "image/png",
      "contentHash": "d2801687418797f175453484d8307ff39eec2b2c7e5b3b358b2cca89671d626e",
      "byteLength": 88557,
      "width": 1804,
      "height": 705
    }
  ],
  "headings": [
    {
      "depth": 1,
      "text": "Unity3D WebGL 框架全景",
      "anchor": "unity3d-webgl-框架全景",
      "citation": "https://www.pystone.net/notes/unity3d-webgl-framework-panorama/#unity3d-webgl-%E6%A1%86%E6%9E%B6%E5%85%A8%E6%99%AF"
    },
    {
      "depth": 3,
      "text": "0|WebGL应用介绍",
      "anchor": "0webgl应用介绍",
      "citation": "https://www.pystone.net/notes/unity3d-webgl-framework-panorama/#0webgl%E5%BA%94%E7%94%A8%E4%BB%8B%E7%BB%8D"
    },
    {
      "depth": 4,
      "text": "容器",
      "anchor": "容器",
      "citation": "https://www.pystone.net/notes/unity3d-webgl-framework-panorama/#%E5%AE%B9%E5%99%A8"
    },
    {
      "depth": 4,
      "text": "共性",
      "anchor": "共性",
      "citation": "https://www.pystone.net/notes/unity3d-webgl-framework-panorama/#%E5%85%B1%E6%80%A7"
    },
    {
      "depth": 3,
      "text": "1 | Emscripten是什么？它和 Clang / LLVM 是什么关系？",
      "anchor": "1-emscripten是什么它和-clang-llvm-是什么关系",
      "citation": "https://www.pystone.net/notes/unity3d-webgl-framework-panorama/#1-emscripten%E6%98%AF%E4%BB%80%E4%B9%88%E5%AE%83%E5%92%8C-clang-llvm-%E6%98%AF%E4%BB%80%E4%B9%88%E5%85%B3%E7%B3%BB"
    },
    {
      "depth": 3,
      "text": "2 | WebAssembly 与传统汇编（二进制机器码）的关系",
      "anchor": "2-webassembly-与传统汇编二进制机器码的关系",
      "citation": "https://www.pystone.net/notes/unity3d-webgl-framework-panorama/#2-webassembly-%E4%B8%8E%E4%BC%A0%E7%BB%9F%E6%B1%87%E7%BC%96%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%9C%BA%E5%99%A8%E7%A0%81%E7%9A%84%E5%85%B3%E7%B3%BB"
    },
    {
      "depth": 3,
      "text": "3 | Glue JS 是什么？它与普通 JavaScript 有何不同？",
      "anchor": "3-glue-js-是什么它与普通-javascript-有何不同",
      "citation": "https://www.pystone.net/notes/unity3d-webgl-framework-panorama/#3-glue-js-%E6%98%AF%E4%BB%80%E4%B9%88%E5%AE%83%E4%B8%8E%E6%99%AE%E9%80%9A-javascript-%E6%9C%89%E4%BD%95%E4%B8%8D%E5%90%8C"
    },
    {
      "depth": 2,
      "text": "Unity → WebGL 构建体系结构全景",
      "anchor": "unity-webgl-构建体系结构全景",
      "citation": "https://www.pystone.net/notes/unity3d-webgl-framework-panorama/#unity-webgl-%E6%9E%84%E5%BB%BA%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84%E5%85%A8%E6%99%AF"
    },
    {
      "depth": 3,
      "text": "1 涉及的语言与职责",
      "anchor": "1-涉及的语言与职责",
      "citation": "https://www.pystone.net/notes/unity3d-webgl-framework-panorama/#1-%E6%B6%89%E5%8F%8A%E7%9A%84%E8%AF%AD%E8%A8%80%E4%B8%8E%E8%81%8C%E8%B4%A3"
    },
    {
      "depth": 3,
      "text": "2 编译工具链",
      "anchor": "2-编译工具链",
      "citation": "https://www.pystone.net/notes/unity3d-webgl-framework-panorama/#2-%E7%BC%96%E8%AF%91%E5%B7%A5%E5%85%B7%E9%93%BE"
    },
    {
      "depth": 3,
      "text": "3 最终产物目录（Unity 2022+ 默认）",
      "anchor": "3-最终产物目录unity-2022-默认",
      "citation": "https://www.pystone.net/notes/unity3d-webgl-framework-panorama/#3-%E6%9C%80%E7%BB%88%E4%BA%A7%E7%89%A9%E7%9B%AE%E5%BD%95unity-2022-%E9%BB%98%E8%AE%A4"
    },
    {
      "depth": 3,
      "text": "4 运行时层级与调用关系",
      "anchor": "4-运行时层级与调用关系",
      "citation": "https://www.pystone.net/notes/unity3d-webgl-framework-panorama/#4-%E8%BF%90%E8%A1%8C%E6%97%B6%E5%B1%82%E7%BA%A7%E4%B8%8E%E8%B0%83%E7%94%A8%E5%85%B3%E7%B3%BB"
    },
    {
      "depth": 3,
      "text": "5 模块职责一览",
      "anchor": "5-模块职责一览",
      "citation": "https://www.pystone.net/notes/unity3d-webgl-framework-panorama/#5-%E6%A8%A1%E5%9D%97%E8%81%8C%E8%B4%A3%E4%B8%80%E8%A7%88"
    },
    {
      "depth": 3,
      "text": "6 JS ↔ Wasm 互操作示例",
      "anchor": "6-js-wasm-互操作示例",
      "citation": "https://www.pystone.net/notes/unity3d-webgl-framework-panorama/#6-js-wasm-%E4%BA%92%E6%93%8D%E4%BD%9C%E7%A4%BA%E4%BE%8B"
    },
    {
      "depth": 3,
      "text": "7 多线程与文件系统补充",
      "anchor": "7-多线程与文件系统补充",
      "citation": "https://www.pystone.net/notes/unity3d-webgl-framework-panorama/#7-%E5%A4%9A%E7%BA%BF%E7%A8%8B%E4%B8%8E%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E8%A1%A5%E5%85%85"
    },
    {
      "depth": 3,
      "text": "8 Unity WebGL vs 微信原生小游戏（复习）",
      "anchor": "8-unity-webgl-vs-微信原生小游戏复习",
      "citation": "https://www.pystone.net/notes/unity3d-webgl-framework-panorama/#8-unity-webgl-vs-%E5%BE%AE%E4%BF%A1%E5%8E%9F%E7%94%9F%E5%B0%8F%E6%B8%B8%E6%88%8F%E5%A4%8D%E4%B9%A0"
    },
    {
      "depth": 3,
      "text": "9 脑内模拟口诀",
      "anchor": "9-脑内模拟口诀",
      "citation": "https://www.pystone.net/notes/unity3d-webgl-framework-panorama/#9-%E8%84%91%E5%86%85%E6%A8%A1%E6%8B%9F%E5%8F%A3%E8%AF%80"
    }
  ],
  "claims": [],
  "outgoing": [],
  "incoming": [
    {
      "id": "note:game-graphics-and-runtime",
      "title": "游戏图形与运行时",
      "url": "https://www.pystone.net/notes/game-graphics-and-runtime/",
      "atlas": "https://www.pystone.net/?node=game-graphics-and-runtime#knowledge-atlas",
      "label": "游戏图形与运行时",
      "origin": "explicit",
      "humanReviewed": true,
      "context": "WebGL中的“Unity3D WebGL 框架全景”导航项",
      "citation": "https://www.pystone.net/notes/game-graphics-and-runtime/#webgl"
    },
    {
      "id": "note:game-dev-graphics-performance",
      "title": "游戏研发、图形与性能",
      "url": "https://www.pystone.net/notes/game-dev-graphics-performance/",
      "atlas": "https://www.pystone.net/?node=game-dev-graphics-performance#knowledge-atlas",
      "label": "游戏研发、图形与性能",
      "origin": "explicit",
      "humanReviewed": true,
      "context": "Unity3D WebGL 框架全景是 Unity 到 WebAssembly、JavaScript 和浏览器环境的桥梁。",
      "citation": "https://www.pystone.net/notes/game-dev-graphics-performance/#%E4%BB%8E%E6%9E%B6%E6%9E%84%E5%88%B0%E8%BF%90%E8%A1%8C%E6%97%B6"
    }
  ],
  "contentMarkdown": "```text\n我现在需要深入理解Unity3D工程构建为WebGL的技术框架。特别是：涉及到哪几种语言，语言编译的工具链是什么，最终产物是什么，涉及到哪些模块或者层级，层级之间的调用关系是什么。这样我可以理解Unity3D - WebGL 应用的完整的体系结构与技术底层，乃至于我基本上能在大脑中模拟、认识应用的完整结构\n```\n\n# Unity3D WebGL 框架全景\n![Web 平台与 WebGL 运行栈](assets/web-platform-stack.png)\n\n### 0|WebGL应用介绍\n\n#### 容器\n> 无论是“标准浏览器 WebGL 应用”还是“微信/抖音小程序版 WebGL”，它们都被装在 **“JS 引擎（逻辑） + 渲染容器（如WebView） + JSBridge”** 这一三层盒子里，而这三层盒子的组合就是广义的 _运行时_。\n\n| 概念                            | 在浏览器里的体现                            | 在小程序里的体现                            | 说明                 |\n| ----------------------------- | ----------------------------------- | ----------------------------------- | ------------------ |\n| **脚本运行时 (JavaScript Engine)** | V8、SpiderMonkey、JavaScriptCore      | 同样是 V8 或 QuickJS 的裁剪版；有时用独立进程       | 真正解释 / JIT JS 的地方  |\n| **渲染容器 (WebView / Canvas)**   | `<canvas>` + GPU 进程 / WebGL context | 宿主 App 内部的轻量级 WebView 或自己实现的 GPU 绑定 | 把像素画到屏幕、接触 GPU     |\n| **系统调用网关 (JSBridge)**         | 原生 Web API 由浏览器统一维护                 | `wx.*` / `tt.*` / `my.*` … 各家实现     | 让 JS 能用摄像头、支付等特权能力 |\n| **安全沙箱**                      | 同源策略、CSP、Iframe 隔离                  | App 级沙箱 + 白名单域名                     | 防数据越界、防恶意脚本        |\n\n#### 共性\n- **前端逻辑全部写成 JavaScript/TypeScript**\n    - 无论是在 PC/Mobile 浏览器里跑的标准 WebGL 游戏，还是嵌入微信、抖音、支付宝的小程序——核心代码都是 JS（或编译到 JS 的 WASM/asm.js），靠同一套事件循环、同一套垃圾回收与语法特性。\n\n- **图形接口都是 WebGL（或 WebGL 封装）**\n    - 浏览器里直接拿 `canvas.getContext('webgl')`。\n    - 小程序侧通常把 WebGL API 重新暴露一遍（如 `wx.createWebGLRenderingContext`、`tt.createWebGLRenderingContext`），底下仍是 OpenGL ES/Metal/Vulkan 到 GPU 的固定流水线。\n\n- **运行在沙箱里的单线程事件循环**\n    - 代码只能通过异步回调或 `postMessage()` 与宿主通信，线程安全由宿主保证。\n    - 内存和文件系统均受限，只能用宿主暴露的 Storage、IndexedDB、临时文件接口。\n\n- **通过“宿主-JSBridge”访问原生能力**\n    - 浏览器的 `Web API`（Fetch、WebSocket、Audio …）。\n    - 小程序的 `wx.* / tt.* / my.*` 能力集合（网络、支付、定位）。\n    - 逻辑上都是把 JS 调用序列化 → 原生线程执行 → 回调结果再序列化回 JS。\n\n### 1 | Emscripten是什么？它和 Clang / LLVM 是什么关系？\n\n| 层级                        | 职责                                                                                                                                                                                                                                                                | 关键产物                        |\n| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- |\n| **Clang**                 | C/C++ 前端：把源码 ➜ 统一的 LLVM IR                                                                                                                                                                                                                                        | `.bc` (LLVM bit‑code)       |\n| **LLVM**                  | 通用优化 & 代码生成框架；包含 wasm32/wasm64 目标后端                                                                                                                                                                                                                               | 优化后的 IR                     |\n| **Emscripten（`emcc` 驱动）** | 把 *“生成 Web 可运行工件”* 所有脏活包揽下来：① 调用 Clang 产出 LLVM IR② 调 `wasm-ld` / Binaryen 优化、链接成 `.wasm` ③ 生成 **Glue JS (`xxx.framework.js`)**，提供 POSIX 运行时、文件系统、`gl*`/`emscripten_*` 系统调用④ 包含 `emcc`, `emar`, `emconfigure` 等前端脚本，像一套 “Unix for WebAssembly” SDK | `.wasm` + `*.js` + `*.html` |\n\n> 简言之：**Clang/LLVM 负责“把 C++ 变 IR→机器码”，Emscripten 负责“把 IR 变 *Web 可执行* + 给它配齐生态”**。Emscripten 在内部仍使用标准 LLVM 后端，但再包上一层 JS Runtime 和工具链特有库。([Stack Overflow][1], [emscripten.org][2])\n\n---\n\n### 2 | WebAssembly 与传统汇编（二进制机器码）的关系\n\n| 维度   | **WebAssembly (.wasm)**          | **传统汇编/机器码 (x86/ARM)**         |\n| ---- | -------------------------------- | ------------------------------ |\n| 目标对象 | 抽象、虚拟的栈机 ISA；与硬件无关               | 针对单一 CPU 架构；寄存器直接暴露            |\n| 格式   | 压缩二进制段 + 结构化控制流                  | 二进制(ELF/PE) 或文本 `.s`           |\n| 安全   | 强沙盒；无指针运算、无自扩写代码；加载时字节级验证        | 原生权限；可能执行任意指令                  |\n| 运行流程 | **下载 → 解析/验证 → JIT/AOT 编译 → 执行** | 已是最终机器码，CPU 直接执行               |\n| 调试符号 | `.wasm.map`, DWARF ► DevTools    | `.pdb`, `.dSYM`, ELF `.symtab` |\n\n**执行链条**\n\n1. 浏览器或 Wasm 运行时读取 `.wasm`，做 **字节码验证**。\n2. 使用 **Baseline JIT**（Chrome Liftoff, Firefox Baseline）快速翻译到本机指令并缓存。\n3. 热路径再交给 **优化 JIT**（Chrome TurboFan, Firefox Ion）重编译，得到接近本地 C++ 性能的机器码。([MDN Web Docs][3], [Stack Overflow][4])\n\n所以 **`.wasm` 是“可移植汇编” → 浏览器即时变成本机汇编**；而传统静态编译直接在构建时就生成特定 CPU 的汇编 / 机器码。\n\n---\n\n### 3 | Glue JS 是什么？它与普通 JavaScript 有何不同？\n\n| 特征        | **Glue JS (`xxx.framework.js`)**                                                                                                                                                                                                 | **手写 JavaScript** |\n| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- |\n| 来源        | **Emscripten 自动生成**                                                                                                                                                                                                              | 开发者撰写             |\n| 职责        | - 加载 & 实例化 `.wasm` (`WebAssembly.instantiateStreaming`)- 构造全局 `Module` 对象，导出 `ccall/cwrap`、FS、GL、Pthreads shim- 把 C/POSIX 调用（`open`, `glDrawArrays`, …）**映射**到浏览器 API 或 TypedArray 操作- 处理字符串/数组在 JS ↔ Wasm 之间的编码、堆管理 | 任意业务逻辑            |\n| 语言        | 仍是标准 ES5/ES6 JS；但大量宏化、函数名压缩、TypedArray 操作                                                                                                                                                                                        | 标准 JS             |\n| 与 Wasm 交互 | 双向 FFI：• JS 调用 `wasm.exports.myFunc` 或 `cwrap`• Wasm 侧通过 `EM_ASM` 或 `dynCall_js` 回到 JS                                                                                                                                   | 仅在 JS 世界          |\n\n> 把它叫“Glue”是因为它 **“黏合”** 两个运行时：一头连 Wasm 的线性内存/函数导出，另一头连浏览器 Web APIs，让 C/C++ 代码能“像在桌面 POSIX 环境”那样调用文件、线程、OpenGL，却最终落到 JS 方法和 WebGL。([emscripten.org][5], [liveBook][6])\n\n[1]: https://stackoverflow.com/questions/64690937/what-is-the-difference-between-emscripten-and-clang-in-terms-of-webassembly-comp?utm_source=chatgpt.com \"llvm - What is the difference between Emscripten and Clang in terms of ...\"\n[2]: https://emscripten.org/docs/introducing_emscripten/about_emscripten.html?highlight=clang&utm_source=chatgpt.com \"About Emscripten — Emscripten 4.0.5-git (dev) documentation\"\n[3]: https://developer.mozilla.org/en-US/docs/WebAssembly?utm_source=chatgpt.com \"WebAssembly | MDN - MDN Web Docs\"\n[4]: https://stackoverflow.com/questions/78337617/how-does-wasm-code-run-in-browsers-and-how-does-it-interact-with-javascript?utm_source=chatgpt.com \"webassembly - How does Wasm code run in browsers and how does it ...\"\n[5]: https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html?utm_source=chatgpt.com \"Interacting with code — Emscripten 4.0.9-git (dev) documentation\"\n[6]: https://livebook.manning.com/book/webassembly-in-action/c-ccall-cwrap-and-direct-method-calls/v-1/?utm_source=chatgpt.com \"C ccall, cwrap, and direct method calls\"\n\n\n## Unity → WebGL 构建体系结构全景\n\n> **一句话先行**\n> Unity 把 **C# 脚本 + C++ 引擎** 经过 **IL2CPP → Emscripten** 编译成 **WebAssembly (.wasm)**，再配上一组 **Glue JS** 和资源包，最终在浏览器里由一段 **Loader 脚本** 拉起运行时，借 **WebGL/WebAudio** 等 API 驱动 GPU 和外设。\n\n---\n\n### 1 涉及的语言与职责\n\n| 语言                       | 典型文件                                       | 在构建链里的角色                   |\n| ------------------------ | ------------------------------------------ | -------------------------- |\n| **C#**                   | `*.cs`（游戏脚本）                               | 被 **IL2CPP** 转成 C++        |\n| **C / C++**              | Unity Runtime（物理、渲染核心）                     | 与脚本一起进 wasm                |\n| **JavaScript**           | `*.loader.js`, `*.framework.js`, `*.jslib` | Glue／Boot loader；桥接浏览器 API |\n| **WebAssembly (binary)** | `*.wasm`                                   | 执行沙盒，承载全部 native 逻辑        |\n| **HTML**                 | `index.html`                               | 页面容器，注入 Loader             |\n| **GLSL ES**              | (打包入 Asset)                                | GPU 着色器，由 WebGL 编译         |\n\n---\n\n### 2 编译工具链\n\n```text\nC# ─► IL2CPP (C# → C++)\n             │\nC/C++ (引擎) ─┤\n             ▼\n        Clang/LLVM\n             │ (via Emscripten)\n             ▼\n        wasm-ld  ──►   unity.wasm\n             │\n      Binaryen/opt   (wasm‑opt, DWARF→map)\n```\n\n* **IL2CPP**：将托管 IL 解码成等价 C++ 源，再交给 C++ 编译器。\n* **Emscripten**：封装 Clang + wasm‑ld；生成 `.wasm` 与 **Glue JS (framework.js)**。([Unity Docs][1])\n* **wasm‑opt / wasm‑strip**：二进制优化、符号剥离。\n* **Brotli/GZIP**：构建后可选压缩，浏览器端解码。([Unity Discussions][2])\n\n---\n\n### 3 最终产物目录（Unity 2022+ 默认）\n\n```text\nBuild/\n ├─ WebGLBuild.loader.js   ← Boot & progress bar\n ├─ WebGLBuild.framework.js← Emscripten glue, Module 对象\n ├─ WebGLBuild.data        ← 资源包 (场景、纹理…)\n ├─ WebGLBuild.wasm        ← C++/C# 编译结果\n ├─ WebGLBuild.js.symbols  ← 堆栈符号 (可选)\n └─ WebGLBuild.wasm.br     ← Brotli 压缩版 (可选)\nindex.html                 ← 模板，可插入脚本/UI\n```\n\n*旧版本只有 `UnityLoader.js` + `UnityWebGL.js`，2020 LTS 起拆分为 `*.loader.js` + `*.framework.js`. ([Stack Overflow][3])*\n\n---\n\n### 4 运行时层级与调用关系\n\n```mermaid\ngraph TD\nA[index.html] --> B(Loader JS)\nB --> C{准备阶段}\nC -->|下载 *.data *.wasm| D(Module.configure)\nD --> E[WebAssembly.instantiateStreaming]\nE --> F{Wasm VM}\nF --> G[Unity Runtime & GameLogic]\nG -->|JSlib/SendMessage| H(Glue JS calls)\nH --> I(Web APIs: WebGL, WebAudio, Input)\nI -->|GPU cmds| J(GPU Driver)\n```\n\n1. **Loader JS** 把文件名映射到 URL（可带解压），显示进度条。\n2. **framework.js** 创建 **`Module` 对象**：\n\n   * 定义 `preloadPlugins`, `onRuntimeInitialized`, `cwrap`, `ccall`。\n3. **`WebAssembly.instantiateStreaming`** 把 `.wasm`+内存映射到 VM。\n4. Wasm 内部通过 **Emscripten syscalls**(`gl*`,`emscripten_*`) 回到 JS 层，再调 WebGL/WebAudio。\n5. **JSlib 插件**：用户写的 `*.jslib` 可通过 `EMSCRIPTEN_BINDINGS` 让 C# 调浏览器 API。\n\n---\n\n### 5 模块职责一览\n\n| 层级               | 主要文件               | 职责                                     | 调用方向                    |\n| ---------------- | ------------------ | -------------------------------------- | ----------------------- |\n| **Boot 入口**      | `.loader.js`       | 找 CDN、本地路径、解压、创建 `<script>`            | ↑ HTML                  |\n| **Glue / Shell** | `.framework.js`    | 配置 Module、映射 `gl*` Syscalls、管理 wasm 内存 | ↔ Boot / Wasm / Browser |\n| **Wasm VM**      | `.wasm`            | 执行 Unity Runtime、游戏脚本 JIT 后逻辑          | ↑ Glue                  |\n| **浏览器 API 层**    | WebGL/WebAudio/DOM | GPU、音频、输入、文件                           | n/a                     |\n\n---\n\n### 6 JS ↔ Wasm 互操作示例\n\n**C# 调 JS**\n\n```csharp\n[DllImport(\"__Internal\")]\nprivate static extern void JsAlert(string msg);\n\nJsAlert(\"Hello WebGL!\");\n```\n\n对应 **plugin.jslib**\n\n```js\nmergeInto(LibraryManager.library, {\n  JsAlert: function (ptr){\n    alert(UTF8ToString(ptr));\n  }\n});\n```\n\n**JS 调 C#**\n\n```js\nModule.ccall('OnExternalEvent', null, ['number'], [42]);\n```\n\n---\n\n### 7 多线程与文件系统补充\n\n* **Pthreads**：`Player Settings ▸ Enable Threads` → Emscripten 生成 `.worker.js`；需 `Cross-Origin-Opener-Policy` 与 `SharedArrayBuffer` 安全头。\n* **Virtual FS**：Emscripten `MEMFS` 把 `*.data` 解包到 wasm 内存；可映射 IndexedDB 做持久化。\n\n---\n\n### 8 Unity WebGL vs 微信原生小游戏（复习）\n\n| 方面  | Unity WebGL      | 原生小游戏                           |\n| --- | ---------------- | ------------------------------- |\n| 语言  | C#/Wasm          | JS/TS                           |\n| 引擎  | Unity Runtime    | WeChat Game Runtime (CocosLite) |\n| 加载链 | Loader JS + Wasm | JS 直跑                           |\n| 包体  | 首包 5‑20 MB       | < 4 MB                          |\n| 渲染  | WebGL            | WebGL/Canvas2D                  |\n| 线程  | Pthreads（灰度）     | 主线程 + Worker                    |\n\n---\n\n### 9 脑内模拟口诀\n\n> **“Loader 找文件 → Glue 创 Module → Wasm 起 VM → Runtime 写 WebGL”**\n\n* 想象 `.wasm` 像 **DLL**；`framework.js` 像 **C 动态链接器**；`loader.js` 像 **启动脚本**。\n* 每次 `glDrawArrays` 源自 Wasm 调用，穿过 Glue 映射成浏览器 WebGL 命令。\n* 所有 C# 调 JS 的桥都在 `.jslib` 汇合；反向则用 `ccall/cwrap`。\n\n掌握这些层级和调用流，你就能在脑海中精准定位：**崩溃发生在哪段、性能瓶颈在何层、要拦截数据应挂在哪边**。后续无论补符号映射、注入监控，亦或改 Loader 自定义 CDN 逻辑，都可胸有成竹。\n\n[1]: https://docs.unity3d.com/6000.1/Documentation/Manual/webgl-native-plugins-with-emscripten.html?utm_source=chatgpt.com \"Manual: Web native plug-ins for Emscripten - Unity\"\n[2]: https://discussions.unity.com/t/compressed-webgl-build-fails-loading/824658?utm_source=chatgpt.com \"Compressed WEBGL Build fails loading - Unity Discussions\"\n[3]: https://stackoverflow.com/questions/75665855/unity-webgl-build-and-run-fails-404-loader-js-missing?utm_source=chatgpt.com \"Unity WebGL Build and Run Fails - 404 .loader.js missing?\"\n"
}
