首先,我得回想一下Unity在WebGL平台下的工作方式。因为WebGL导出后运行在浏览器环境中,Unity和JavaScript可以通过互调机制进行通信。用户可能需要从C#调用JS函数,或者从JS调用C#方法。不过要注意WebGL的限制,比如线程问题,因为Unity WebGL是单线程的,所有C#和JS的交互都需要在主线程进行。

接下来,用户可能的具体需求是什么?他们可能需要访问某些浏览器特定的功能,比如本地存储、AJAX请求,或者使用某个现有的JS库,比如图表库、社交分享等。另外,可能涉及到前后端的数据交互,比如通过JS发送HTTP请求到服务器,然后将结果传回Unity。

我需要分步骤回答。首先介绍基本的C#调用JS的方法,使用[DllImport("__Internal")],然后举例子,比如在C#中调用一个JS函数。然后反过来,如何在JS中调用C#方法,可能需要使用SendMessage或者直接调用编译后的C#函数。还要提到参数传递的注意事项,比如字符串、数字、数组等的处理方式,可能需要使用JSON.stringify和JSON.parse来转换复杂数据结构。

另外,需要提醒用户关于平台依赖的问题,这些代码只在WebGL平台下有效,所以在其他平台编译时需要条件编译或者避免调用。还要提到一些常见问题,比如异步调用的处理,因为JS的一些操作可能是异步的,比如AJAX请求,这时候C#需要等待回调,可能需要使用协程或者回调函数。

可能用户还会关心性能问题,频繁的C#和JS互调可能会影响性能,尤其是在移动端浏览器上。需要建议尽量减少跨语言调用的次数,或者将数据批量处理。

然后,可以举一个实际的例子,比如在Unity中调用JS的alert函数,或者在JS中调用Unity中的方法更新游戏状态。还要提到使用jslib文件来封装复杂的JS代码,这样在C#中调用会更方便。

另外,可能需要处理事件监听,比如在JS中监听浏览器窗口的大小变化,然后通知Unity调整游戏画面的分辨率。这时候需要在JS中编写事件处理函数,并通过SendMessage通知Unity。

最后,总结一下步骤和注意事项,确保用户能够正确实现通信功能,避免常见的陷阱,比如跨域问题、数据类型转换错误等。

在 Unity WebGL 项目中,C# 与 JavaScript 的通信可以通过 浏览器互操作(Browser Interop) 实现。以下是详细的实现方法:


一、C# 调用 JavaScript 函数

1. 基础方法:使用 [DllImport("__Internal")]

csharp

Copy

using System.Runtime.InteropServices;

public class JSBridge : MonoBehaviour
{
    // 声明 JavaScript 函数
    [DllImport("__Internal")]
    private static extern void ShowAlert(string message);

    void Start()
    {
        // 调用 JavaScript 函数
        ShowAlert("Hello from Unity!");
    }
}
2. 在项目中添加 .jslib 文件
  • 在 Assets/Plugins/WebGL 目录下创建 WebGLPlugin.jslib

javascript

Copy

mergeInto(LibraryManager.library, {
    ShowAlert: function (message) {
        // 调用浏览器 API
        alert(Pointer_stringify(message));
    }
});

二、JavaScript 调用 C# 函数

1. 通过 SendMessage 调用 GameObject 方法

csharp

Copy

// C# 脚本
public class MessageReceiver : MonoBehaviour
{
    public void HandleJSMessage(string message)
    {
        Debug.Log("Received from JS: " + message);
    }
}

javascript

Copy

// JavaScript 代码(在浏览器中执行)
// 调用 Unity 场景中名为 "Communicator" 的 GameObject 的 "HandleJSMessage" 方法
unityInstance.SendMessage('Communicator', 'HandleJSMessage', 'Hello from JS!');
2. 直接调用编译后的 C# 方法(需要启用 UNITY_WEBGL 宏)

csharp

Copy

// C# 脚本(启用导出为 JS)
#if UNITY_WEBGL && !UNITY_EDITOR
    [DllImport("__Internal")]
    public static extern void JSCallToCSharp();
#else
    public static void JSCallToCSharp() { }
#endif

// 在 C# 中定义供 JS 调用的方法
public static void ReceiveFromJS(string data) {
    Debug.Log("JS Data: " + data);
}

javascript

Copy

// JavaScript 中调用(通过全局函数)
// Unity 导出的全局对象为 `unityInstance`
unityInstance.Module.ReceiveFromJS("This is JS data");

三、参数传递与数据类型

1. 基本类型
  • C# → JS:直接传递 stringintfloat

  • JS → C#:使用 Pointer_stringify 处理字符串。

2. 复杂类型(JSON 序列化)

csharp

Copy

// C# 发送 JSON
[DllImport("__Internal")]
private static extern void SendDataToJS(string json);

void SendComplexData() {
    var data = new { name = "Unity", value = 100 };
    SendDataToJS(JsonUtility.ToJson(data));
}

javascript

Copy

// JS 接收并解析 JSON
mergeInto(LibraryManager.library, {
    SendDataToJS: function (json) {
        const data = JSON.parse(Pointer_stringify(json));
        console.log("Received:", data.name, data.value);
    }
});

四、实战示例:Unity 与 JS 双向通信

1. Unity 调用 JS 的摄像头 API

javascript

Copy

// WebGLPlugin.jslib
mergeInto(LibraryManager.library, {
    RequestCameraAccess: function () {
        navigator.mediaDevices.getUserMedia({ video: true })
            .then(stream => {
                // 将视频流传递给 Unity
                const video = document.createElement('video');
                video.srcObject = stream;
                video.play();
                unityInstance.SendMessage('CameraManager', 'OnCameraReady', '');
            })
            .catch(err => {
                console.error("Camera error:", err);
            });
    }
});

csharp

Copy

// C# 脚本
public class CameraManager : MonoBehaviour
{
    [DllImport("__Internal")]
    private static extern void RequestCameraAccess();

    void Start()
    {
        RequestCameraAccess();
    }

    // JS 回调方法
    public void OnCameraReady()
    {
        Debug.Log("Camera is ready!");
    }
}

五、注意事项

  1. 平台限制

    • 仅在 WebGL 平台有效,需使用 #if UNITY_WEBGL 条件编译。

    • 在 Unity Editor 中无法直接调试,需导出为 WebGL 后测试。

  2. 性能优化

    • 避免高频跨语言调用(如每帧调用)。

    • 复杂数据优先使用 JSON 序列化。

  3. 安全性

    • 对 JS 传入的数据做校验,防止注入攻击。


六、扩展功能

  1. 与第三方 JS 库集成

    • 在 HTML 模板中引入外部库(如 axiosThree.js):

    html

    Copy

    <!-- index.html -->
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

    Run HTML

    • 通过 .jslib 调用库方法。

  2. 异步操作处理

    csharp

    Copy

    // C# 协程等待 JS 回调
    IEnumerator WaitForJSResponse()
    {
        bool isDone = false;
        JSBridge.RequestAsyncData(() => { isDone = true; });
        yield return new WaitUntil(() => isDone);
    }
  3. 错误处理

    javascript

    Copy

    // JS 错误捕获
    try {
        unityInstance.SendMessage(...);
    } catch (e) {
        console.error("Unity call failed:", e);
    }

通过上述方法,可以实现 Unity C# 与 JavaScript 的高效通信,适用于 WebGL 游戏、数据可视化、浏览器 API 集成等场景。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐