Unity WebGL中如何从C#脚本调用异步JavaScript函数?
问题原因
Unity WebGL通过DllImport调用JS函数是同步机制,而你定义的async函数返回的是Promise对象,并非直接的字符串结果,同步调用无法解析Promise,因此C#脚本拿不到钱包地址。
解决方案:用UnitySendMessage实现异步回调
Unity WebGL处理JS异步交互的标准方式是通过UnitySendMessage,让JS在异步操作完成后主动将结果传递给C#脚本。
1. 修改JSlib文件
移除async返回逻辑,改为在MetaMask请求完成后,通过UnitySendMessage将结果发送到C#的指定方法:
mergeInto(LibraryManager.library, { RequestMetaMaskWallet: function() { window.ethereum.request({ method: 'eth_requestAccounts' }) .then(accounts => { const account = accounts[0]; // 向Unity指定对象的方法发送结果 // 参数1:挂载C#脚本的游戏对象名称,参数2:C#方法名,参数3:传递的字符串 UnitySendMessage("WalletManager", "OnMetaMaskConnected", account); }) .catch(err => { if (err.code === 4001) { console.log('用户拒绝连接MetaMask'); } else { console.error(err); } // 发送空字符串标识连接失败/拒绝 UnitySendMessage("WalletManager", "OnMetaMaskConnected", ""); }); }, });
2. 修改C#脚本
添加接收JS回调的方法,调整调用逻辑为触发异步请求而非同步等待返回:
using UnityEngine; using UnityEngine.UI; using System.Runtime.InteropServices; public class WalletManager : MonoBehaviour { [DllImport("__Internal")] private static extern void RequestMetaMaskWallet(); public Button connectMetaMaskButton; void Start() { Button btn = connectMetaMaskButton.GetComponent<Button>(); btn.onClick.AddListener(ConnectWallet); } void ConnectWallet() { // 触发JS的异步请求,不等待返回 RequestMetaMaskWallet(); // 临时禁用按钮防止重复点击 connectMetaMaskButton.interactable = false; } // 必须是public方法,用于接收JS的回调 public void OnMetaMaskConnected(string account) { // 恢复按钮状态 connectMetaMaskButton.interactable = true; if (!string.IsNullOrEmpty(account)) { Debug.Log("钱包连接成功:" + account); connectMetaMaskButton.gameObject.SetActive(false); // 这里可以继续处理钱包地址(比如显示到UI、存储到本地等) } else { Debug.Log("连接失败或用户拒绝授权"); // 可添加提示用户重新尝试的逻辑 } } }
关键注意事项
- 确保挂载C#脚本的游戏对象名称是
WalletManager(与JS中UnitySendMessage的第一个参数完全一致),如果对象改名,JS里也要同步修改。 - C#的
OnMetaMaskConnected方法必须是public,且参数类型为string,否则JS无法调用。 - 必须在浏览器环境下测试(WebGL构建后或Unity的WebGL预览模式),MetaMask不支持Unity编辑器的本地PlayMode。
内容的提问来源于stack exchange,提问作者user21810601
相关产品推荐
相关产品推荐

