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

Unity WebGL对接社交平台API时,异步回调场景下如何正确从函数返回数据?

Unity WebGL对接社交平台API时,异步回调场景下如何正确从函数返回数据?

兄弟,我太懂你现在的头疼之处了——原来用PlayerPrefs是同步拿值,换成社交平台的异步API后,直接同步返回的路子完全走不通,要么拿空值,要么执行顺序全乱。核心问题在于WebGL里Unity和JS的异步交互不能用同步返回的逻辑,得彻底换个思路,下面给你几个落地的解决方案:

一、先把同步接口改成异步回调模式

你原来的IMapProgressManager里的LoadLevelStarsCount是同步返回int,这在异步场景下根本行不通,得先重构接口,让它接受一个回调函数,等数据拿到后再触发后续逻辑:

// 重构后的接口
public interface IMapProgressManager
{
    // 把同步返回改成带回调参数的异步方法
    void LoadLevelStarsCount(int level, Action<int> onStarsLoaded);
    // 其他方法也同理改成异步模式
}

然后修改你的PlayerPrefsMapProgressManager实现,把异步逻辑串起来:

public class PlayerPrefsMapProgressManager : IMapProgressManager
{
    public JSBridgeController bridge;
    
    public void LoadLevelStarsCount(int level, Action<int> onStarsLoaded)
    {
        // 调用JS获取数据,把回调和关卡键绑定(避免多请求混淆)
        var levelKey = GetLevelKey(level);
        bridge.JSStorageGet(levelKey, (value) => 
        {
            // 拿到JS返回的值后转成int,再触发回调
            int stars = int.TryParse(value, out var result) ? result : 0;
            onStarsLoaded?.Invoke(stars);
        });
    }

    // 原来的GetLevelKey方法保留
    private string GetLevelKey(int level)
    {
        return $"Level_{level}_Stars";
    }
}

调用方也得改成通过回调处理后续逻辑,不能直接拿返回值:

// 比如在UI或游戏逻辑里这样调用
mapProgressManager.LoadLevelStarsCount(1, (stars) => 
{
    // 这里拿到正确的星星数后再更新UI或逻辑
    Debug.Log($"第1关星星数:{stars}");
    // 示例:更新关卡显示 levelUI.SetStars(stars);
});

二、修复JS层的异步执行问题

你后来提到JS里的myBridge.send是异步的,原来的_JSStorageGet试图直接return肯定不行——因为then里的逻辑是在C#函数执行完之后才会跑,所以C#那边先拿到了默认值,JS的日志才出来。得把JS里的逻辑改成通过SendMessage把结果推给Unity,而不是返回值:

修改你的jsbridge.jslib:

mergeInto(LibraryManager.library, {
  _JSStorageSet: function (keyPtr, valuePtr) {
    var key = UTF8ToString(keyPtr);
    var value = UTF8ToString(valuePtr);
    // 调用社交平台的set接口
    myBridge.send("StorageSet", {"key": key, "value": value});
  },
  _JSStorageGet: function (keyPtr) {
    var key = UTF8ToString(keyPtr);
    // 异步调用社交平台的get接口
    myBridge.send("StorageGet", {"keys": [key]}).then(data => {
      var resultValue = "0"; // 默认值
      if (data.keys[0].value) {
        resultValue = data.keys[0].value;
      }
      // 把结果通过SendMessage传给Unity的JSBridgeHandler
      ss.SendMessage('JSBridge', 'ResultStorageGet', resultValue);
    });
  }
});

然后确保你的JSBridgeController里的JSStorageGet还是用回调存储的逻辑:

public class JSBridgeController : MonoBehaviour
{
    [DllImport("__Internal")]
    public static extern void _JSStorageSet(string key, string value);
    [DllImport("__Internal")]
    public static extern void _JSStorageGet(string key); // 这里改成void,不要返回值

    public UnityAction<string> _actionStorageGet;

    public void JSStorageGet(string key, UnityAction<string> action)
    {
#if !UNITY_EDITOR
        _actionStorageGet = action;
        _JSStorageGet(key);
#endif
    }

    // ...其他代码保留
}

这样JS那边异步拿到数据后,会主动通知Unity触发回调,执行顺序就完全正确了。

三、千万别用“延迟等待”的歪路子

你之前想加个delay等回调,这绝对是坑——异步操作的时间完全不确定,可能网络慢一点延迟就不够,或者网络快了白等,而且WebGL里用协程WaitForSeconds也没法真的阻塞同步函数。彻底放弃同步返回的想法,拥抱异步回调才是正确方向。

备注:内容来源于stack exchange,提问作者Марк

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 14:59:31