1. 问题现象与背景分析
最近在Unity开发微信小游戏时,不少开发者遇到了一个典型的授权报错:"getUserInfo:fail click action before resolve is needed"。这个错误通常发生在尝试获取用户信息时,但用户尚未完成必要的点击授权操作。
微信小游戏的授权机制与普通网页不同,它采用了"先点击后授权"的安全策略。当你的Unity游戏通过微信JS-SDK调用wx.getUserInfo接口时,必须确保用户已经主动点击了页面上的某个按钮元素。这个设计是为了防止开发者静默获取用户信息,保护用户隐私。
2. 错误原因深度解析
2.1 授权流程时序问题
这个报错的根本原因是授权流程的时序错误。微信小游戏要求:
- 必须有一个可点击的UI元素(通常是按钮)
- 用户必须先点击这个元素
- 点击事件处理函数中才能调用wx.getUserInfo
很多开发者容易犯的错误是:
- 在游戏初始化时就调用获取用户信息
- 将授权调用放在非用户交互触发的逻辑中
- 使用Unity的UI系统而非微信原生按钮
2.2 Unity与微信API的交互特点
Unity WebGL构建的小游戏运行在微信环境中时,需要通过JavaScript桥接层与微信API交互。这个过程中有几个关键点:
- Unity不能直接调用微信JS-SDK,需要通过jslib插件中转
- 微信的点击事件必须绑定到原生DOM元素上
- 授权弹窗的触发必须来自真实的用户点击事件
3. 完整解决方案
3.1 前端准备:创建授权按钮
首先需要在HTML模板中添加授权按钮。修改Unity导出的index.html,在
中添加:<button id="authButton" style="position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); padding:12px 24px; font-size:16px;"> 点击授权 </button>3.2 Unity与JavaScript交互
创建jslib插件文件(如WeChatAuth.jslib):
mergeInto(LibraryManager.library, { RequestUserAuth: function() { document.getElementById('authButton').onclick = function() { wx.getUserInfo({ success: function(res) { // 将用户信息传回Unity var userInfo = JSON.stringify(res.userInfo); var buffer = _malloc(userInfo.length + 1); stringToUTF8(userInfo, buffer, userInfo.length + 1); _AuthSuccess(buffer); _free(buffer); }, fail: function(res) { var errMsg = JSON.stringify(res.errMsg); var buffer = _malloc(errMsg.length + 1); stringToUTF8(errMsg, buffer, errMsg.length + 1); _AuthFail(buffer); _free(buffer); } }); }; } });3.3 Unity C#脚本实现
创建AuthManager.cs脚本:
using UnityEngine; using System.Runtime.InteropServices; public class AuthManager : MonoBehaviour { [DllImport("__Internal")] private static extern void RequestUserAuth(); [DllImport("__Internal")] private static extern void _AuthSuccess(string userInfo); [DllImport("__Internal")] private static extern void _AuthFail(string errMsg); void Start() { #if !UNITY_EDITOR && UNITY_WEBGL RequestUserAuth(); #endif } // 由JavaScript调用的成功回调 public void OnAuthSuccess(string userInfoJson) { var userInfo = JsonUtility.FromJson<WeChatUserInfo>(userInfoJson); Debug.Log($"授权成功: {userInfo.nickName}"); // 隐藏授权按钮 #if !UNITY_EDITOR && UNITY_WEBGL Application.ExternalEval("document.getElementById('authButton').style.display='none';"); #endif } // 由JavaScript调用的失败回调 public void OnAuthFail(string errMsg) { Debug.LogError($"授权失败: {errMsg}"); } } [System.Serializable] public class WeChatUserInfo { public string nickName; public string avatarUrl; public string gender; public string city; public string country; public string province; public string language; }3.4 微信配置注意事项
在微信小游戏后台需要确保:
- 已添加"用户信息"权限
- 域名已正确配置
- 基础库版本不低于1.2.0
4. 常见问题排查
4.1 按钮点击无反应
可能原因:
- 按钮被Unity canvas遮挡
- z-index设置不当
- 按钮尺寸过小
解决方案:
#authButton { z-index: 9999; width: 200px; height: 80px; }4.2 授权弹窗不出现
检查步骤:
- 确认wx.config已成功执行
- 检查是否有其他JavaScript错误
- 确保调用时机在用户点击事件处理函数内
4.3 用户拒绝授权后的处理
需要在fail回调中添加重新授权逻辑:
fail: function(res) { if(res.errMsg.indexOf('deny') > -1) { // 用户拒绝,显示重新授权提示 document.getElementById('authButton').innerText = '请点击授权以继续游戏'; document.getElementById('authButton').style.display = 'block'; } }5. 性能优化建议
- 延迟加载用户信息:不要一开始就请求授权,等用户进入需要个人信息的场景时再触发
- 缓存用户信息:使用微信的storage API保存已授权信息
- 渐进式授权:先获取基本权限,需要时再请求完整信息
6. 完整实现流程图
- 游戏启动 → 显示授权按钮
- 用户点击 → 触发微信授权弹窗
- 用户确认 → 获取用户信息 → 隐藏按钮
- 用户拒绝 → 显示重新授权提示
7. 微信API更新适配
随着微信API的更新,授权流程可能会有变化。目前最新版本(2023)需要注意:
- 必须使用
- open-type="getUserInfo"已废弃,需改用新API
- 需要同时配置wx.login和wx.getUserInfo
8. 跨平台兼容处理
为了让代码在编辑器和WebGL平台都能运行:
void Start() { #if UNITY_EDITOR // 模拟用户信息 var testUser = new WeChatUserInfo { nickName = "测试用户", avatarUrl = "" }; OnAuthSuccess(JsonUtility.ToJson(testUser)); #elif UNITY_WEBGL RequestUserAuth(); #endif }9. 安全注意事项
- 不要在前端存储敏感信息
- 服务端需要验证微信返回的签名
- 用户信息需要做XSS防护
10. 扩展功能实现
获取更多用户信息时,可以在成功回调中添加:
wx.getSetting({ success: function(res) { if(res.authSetting['scope.userInfo']) { wx.getUserInfo({ withCredentials: true, success: function(res) { // 包含encryptedData和iv等敏感数据 } }); } } });在实际项目中,我通常会创建一个专门的授权管理类来处理所有微信交互,这样既保持了代码整洁,又方便统一处理错误和重试逻辑。记住,微信小游戏的授权流程可能会继续变化,保持对官方文档的关注很重要。