Unity WebGL+WebXR 传输问题与方案 / Unity WebGL+WebXR Transport Issues & Fixes

背景 / Context

博主在尝试使用 Unity WebXR Export 导出项目为 WebXR App 时,遇到了 App 通信问题:原本利用 UDP/WebSocket 与外部 server 传输数据,但导出的 WebXR App 始终无法建立通信。
While exporting a Unity project to WebXR with Unity WebXR Export, I hit a networking wall: the app originally used UDP/WebSocket to talk to an external server, but the exported WebXR app could never establish the connection.

(Unity WebXR Export: https://github.com/De-Panther/unity-webxr-export 是一个很好的导出工具,如果你想把 Unity 项目转成 WebXR 应用。)
(Unity WebXR Export: https://github.com/De-Panther/unity-webxr-export is a solid tool if you want to ship your Unity project as a WebXR app.)

  • 原本做法(简化示例)/ Original approach (simplified):
    using System.Net.Sockets;
    using System.Net.WebSockets;
    using System.Text;
    using System.Threading;
    
    // UDP 方式
    udp = new UdpClient();
    udp.Connect(remoteIP, remotePort);
    udp.Send(Encoding.UTF8.GetBytes(payload), payload.Length);
    
    // 或使用 ClientWebSocket
    ws = new ClientWebSocket();
    await ws.ConnectAsync(new Uri(wssUrl), CancellationToken.None);
    await ws.SendAsync(data, WebSocketMessageType.Text, true, CancellationToken.None);
    
    构建 WebGL 后,这些调用在浏览器里不会启动任何网络连接。
    After WebGL build, these UDP/ClientWebSocket calls never start a network connection in the browser.
  • 遇到的问题:Unity WebXR 导出后,HUD 显示“WS State: Connecting”,后端中继/UDP 无数据;UDP/ClientWebSocket 在 WebGL 下完全不工作。
    Issue met: After Unity WebXR export, HUD stuck at “WS State: Connecting”, backend relay/UDP sees nothing; UDP/ClientWebSocket simply don’t work in WebGL.
  • 根因:Unity 官方文档说明 Web 平台不支持 .NET System.Net 套接字,也不支持原生 UDP/Ping/ClientWebSocket(参考 https://docs.unity3d.com/Manual/webgl-networking.html)。
    Root cause: Web blocks .NET System.Net sockets; no native UDP/Ping/ClientWebSocket.
  • 结果:WebGL/WebXR 下原生 UDP/WS 代码会卡在 “Connecting” 或直接失败。
    Result: Native UDP/WS in WebGL/WebXR stalls at “Connecting” or fails.
  • 关键限制 / Key limitation: 在 WebGL/WebXR 里无法使用 UDP;必须走浏览器的 WebSocket(ws/wss)。
    UDP is not usable in WebGL/WebXR; you must use browser WebSocket (ws/wss).

方案 / Approach

  1. 使用浏览器 WebSocket API

    • JS 插件 Assets/WebGLPlugins/WebSocketPlugin.jslib 暴露 WS_Connect/WS_Send/WS_Close,走浏览器 WS。
      JS plugin exposes WS_Connect/WS_Send/WS_Close to use browser WebSocket.
      mergeInto(LibraryManager.library, {
        WS_Socket: null,
        WS_Connect: function (urlPtr) {
          const url = UTF8ToString(urlPtr);
          Module.WS_Socket = new WebSocket(url);
          Module.WS_Socket.onopen = () => console.log("WS open", url);
          Module.WS_Socket.onerror = (e) => console.log("WS error", e);
          Module.WS_Socket.onclose = () => console.log("WS closed");
        },
        WS_Send: function (msgPtr) {
          if (!Module.WS_Socket || Module.WS_Socket.readyState !== WebSocket.OPEN) return;
          Module.WS_Socket.send(UTF8ToString(msgPtr));
        },
        WS_Close: function () {
          if (Module.WS_Socket) Module.WS_Socket.close();
        },
      });
      
    • WebGL 端脚本调用插件进行通信(示例) / WebGL C# usage example:
      using System.Runtime.InteropServices;
      using UnityEngine;
      
      public class WebGLWsSender : MonoBehaviour
      {
          [DllImport("__Internal")] private static extern void WS_Connect(string url);
          [DllImport("__Internal")] private static extern void WS_Send(string msg);
          [DllImport("__Internal")] private static extern void WS_Close();
      
          public string wsUrl = "ws://localhost:8765";
          public string testMessage = "hello from WebGL";
      
          void Start() => WS_Connect(wsUrl);   // 在 Start 中建立连接 / Connect in Start
      
          void Update()
          {
              if (Input.GetKeyDown(KeyCode.Space))
              {
                  WS_Send(testMessage);        // 按空格发送测试消息 / Send on space key
              }
          }
      
          void OnApplicationQuit() => WS_Close(); // 退出时关闭 / Close on quit
      }
      
  2. WSS 与证书 / WSS & Certificates

    • 页面是 HTTPS 时必须用 WSS(浏览器拦截 ws://)。
      If the page is HTTPS, WSS is required (ws:// is blocked).
    • 自签示例 / Self-signed example:
      openssl req -newkey rsa:2048 -nodes -keyout selfsigned.key -x509 -days 365 -out selfsigned.crt
      python3 wss_udp_relay.py --ws-host 0.0.0.0 --ws-port 8765 --udp-host 127.0.0.1 --udp-port 9000 --use-ssl --certfile selfsigned.crt --keyfile selfsigned.key
      
    • 关键:浏览器需先访问 https://<relay-ip>:<port> 接受自签证书,之后 wss://<relay-ip>:<port> 才能握手(Quest/PC 浏览器同理)。
      Important: You must visit https://<relay-ip>:<port> once to accept the self-signed cert, then wss://<relay-ip>:<port> will succeed.
    • 生产建议用可信 CA 证书。
      For production, use a trusted CA cert.

使用步骤 / How to Use

WebXR 端 / WebXR side

  1. 放置 JS 插件 Assets/WebGLPlugins/WebSocketPlugin.jslib
    Place the JS plugin under Assets/WebGLPlugins/WebSocketPlugin.jslib.
  2. 使用一个 WebGL 脚本调用 WS_Connect/WS_Send/WS_Close,设置 wsUrlws://wss://)。
    Use a WebGL C# script calling WS_Connect/WS_Send/WS_Close, set wsUrl (ws:// or wss://).
  3. 构建 WebGL;如是 HTTPS,按上文处理证书并在浏览器信任。
    Build WebGL; if HTTPS, handle certs and trust in the browser.
  4. 数据流:WebGL → WS/WSS → /WS 接收端。
    Flow: WebGL → WS/WSS → WS receiver.

快速检查 / Quick checklist

  • wsUrl 协议/主机/端口是否正确,HTTPS 场景是否用 WSS。
    wsUrl scheme/host/port correct; WSS required if page is HTTPS.
  • 自签证书是否已在浏览器手动信任。
    Self-signed cert trusted by visiting https://<relay-ip>:<port>.
  • Relay 日志是否有 “client connected”/转发字节。
    Relay logs show “client connected” and forwarded bytes.
  • 接收端端口是否正确监听(UDP 或 WS)。
    Receiver listening on the right port (UDP or WS).

作 者:motorbottle
链 接: https://blog.motorbottle.site/archives/695
来 源:Motor's Blog
版 权 声 明:本博客所有文章除特别声明(如【转载】)外,均采用CC BY-NC-SA 4.0许可协议。文章版权归作者所有,未经允许请勿转载!


暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇