You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity3D WebGL 如何将JS中web3异步调用结果返回至Unity端

问题根因

你的推测完全正确,web3.eth.call属于异步网络请求操作,回调函数会在网络响应返回后才执行,而js函数的return语句会在发起请求后立即执行,此时balance还是初始的默认值,所以Unity侧同步接收的返回值永远不会是实际查询结果。

解决方案

Unity WebGL提供了JS侧主动调用C#方法的能力,你可以在异步请求拿到结果后,通过SendMessage接口主动把结果回传给Unity侧的指定方法,不需要通过同步返回值的方式获取结果。


1. 修改.jslib侧代码

web3 = new Web3(new Web3.providers.HttpProvider("xxxx"));

GetBalance: function (str) {
    var addr = (Pointer_stringify(str));
    var contractAddr = ('xxxx');
    var tknAddress = (addr).substring(2);
    var contractData = ('0x70a08231000000000000000000000000' + tknAddress);
    
    web3.eth.call({
        to: contractAddr, 
        data: contractData 
    }, function(err, result) {
        if (result) { 
            var tokens = web3.utils.toBN(result).toString();
            var balance = web3.utils.fromWei(tokens, 'kwei');
            console.log('Tokens Owned: ' + balance); 
            // 回传结果给Unity,三个参数分别是:接收消息的GameObject名、回调方法名、传递的参数
            Module.SendMessage('WalletManager', 'OnBalanceFetched', balance);
        } else {
            console.log(err);
            // 可选:错误信息也可以回传给Unity做提示
            Module.SendMessage('WalletManager', 'OnBalanceFetchError', err.message);
        }
    });
}

说明:SendMessage的第一个参数必须和Unity场景中挂载回调脚本的GameObject名称完全一致,大小写敏感。如果Module.SendMessage调用失败,可以在WebGL构建产物的index.html中,createUnityInstance的成功回调里添加window.unityInstance = unityInstance;,之后用window.unityInstance.SendMessage调用即可。


2. 修改Unity侧C#代码

using UnityEngine;
using UnityEngine.UI;
using System.Runtime.InteropServices;

public class WalletManager : MonoBehaviour // 这个脚本要挂载在名为WalletManager的GameObject上
{
    public Text ButtonText;

    [DllImport("__Internal")] 
    private static extern void GetBalance(string s); // 改为无返回值,异步接收结果

    public void Start() { 
        string s = WalletAddress();
        GetBalance(s); // 发起异步查询,不需要同步等返回
    }

    // JS侧会主动调用这个方法接收余额结果
    public void OnBalanceFetched(string balance)
    {
        // 直接更新UI或存储变量即可,调用自动在Unity主线程执行,不需要额外处理线程安全
        ButtonText.text = balance;
    }

    // 可选:接收错误信息的回调
    public void OnBalanceFetchError(string errorMsg)
    {
        Debug.LogError($"查询余额失败:{errorMsg}");
        ButtonText.text = "查询失败";
    }

    // 你的原有获取钱包地址的方法
    private string WalletAddress()
    {
        // 原有逻辑
        return "";
    }
}

注意事项

  • 如果需要传递复杂结构体,可以先在JS侧序列化为JSON字符串,C#侧收到后再反序列化即可
  • 回调方法必须是挂载在目标GameObject上的public实例方法,不能是静态方法、私有方法
  • 不要在异步回调里调用JS的内存释放相关方法处理传入的字符串参数,Unity会自动管理这部分内存

内容的提问来源于stack exchange,提问作者kyntyn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 08:51:01