赞
踩
用Unity
开发微信小游戏过程中,想要获取用户信息,遇到了许多坑位,这里记录一下
以下步骤仅提供参考
有些细则可在官方文档或官方Demo查看,可能隐藏较深,需耐心翻找,并且很多适配API的文档需在源码注释里找
用户信息属于敏感数据,想获取需要授权,而想授权成功则需要同意隐私协议。所以,需要到微信公众号平台设置隐私协议
PS:坑位一,这些在官方文档几乎没提到,不然就是隐藏极深
设置 > 服务内容声明
Loader
Loader
Start Game
,用于表示开始游戏Loader
脚本的函数其中,按钮作用主要是为了引导用户点击授权区域
以下是脚本内容,具体可看代码注释
大致的步骤是
PS:坑位二,在Unity中,WX.CreateUserInfoButton创建的是一个透明区域,透明啊!!!这两个字只在官方Demo及源码注释中提了一嘴,不知道还以为没生效呢,这也是为什么需要一个按钮来引导点击的原因
using System.Collections; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; using WeChatWASM; public class LoaderTest : MonoBehaviour { /// <summary> /// 用户信息 /// 获取到用户信息后可根据需要存云端或本地持久存储 /// </summary> public WXUserInfo userInfo; /// <summary> /// 是否获取用户信息 /// </summary> private bool infoFlag = false; /// <summary> /// 头像材质 /// </summary> public Texture2D avatarTexture; // Start is called before the first frame update void Start() { // 初始化微信SDK WX.InitSDK((code) => { Debug.Log("init WXSDK code: " + code); // 加载用户信息 this.LoaderWXMess(); }); } /// <summary> /// 加载微信授权相关信息 /// </summary> private void LoaderWXMess() { // 1. 询问隐私协议授权情况 WX.GetPrivacySetting(new GetPrivacySettingOption() { success = (res) => { /** * needAuthorization - 含义 * 是否需要用户授权隐私协议(如果开发者没有在[mp后台-设置-服务内容声明-用户隐私保护指引]中声明隐私收集类型则会返回false; * 如果开发者声明了隐私收集,且用户之前同意过隐私协议则会返回false; * 如果开发者声明了隐私收集,且用户还没同意过则返回true; * 如果用户之前同意过、但后来小程序又新增了隐私收集类型也会返回true) */ // 询问成功 if (res.needAuthorization) { // 有隐私协议,且未授权 // 2. 发起隐私协议授权 // 弹出隐私协议询问弹窗 WX.RequirePrivacyAuthorize(new RequirePrivacyAuthorizeOption() { success = (res) => { Debug.Log("同意隐私协议:" + JsonUtility.ToJson(res, true)); // 用户同意隐私协议 // 3. 获取用户信息 this.GetScopeInfoSetting(); // 将 信息获取标志 标记为true this.infoFlag = true; }, fail = (err) => { Debug.Log("拒绝隐私协议:" + JsonUtility.ToJson(res, true)); }, complete = (res) => { Debug.Log("询问隐私协议结束"); } }); } }, fail = (err) => { }, complete = (res) => { // 处理询问隐私协议失败或之前已经同意但未授权用户信息的情况 if (!this.infoFlag) { this.GetScopeInfoSetting(); } } }); } /// <summary> /// 点击开始游戏 /// </summary> public void StartGame() { Debug.Log("start game"); Debug.Log("用户信息:" + JsonUtility.ToJson(this.userInfo, true)); } /// <summary> /// 获取授权 /// </summary> private void GetScopeInfoSetting() { // 询问用户信息授权情况 WX.GetSetting(new GetSettingOption() { success = (res) => { Debug.Log("获取用户信息授权情况成功: " + JsonUtility.ToJson(res.authSetting, true)); // 判断用户信息的授权情况 if (!res.authSetting.ContainsKey("scope.userInfo") || !res.authSetting["scope.userInfo"]) { // 3.1 未授权,创建授权按钮区 // 需引导用户点击所创建的区域,这里的做法是将开始游戏的按钮放在该区域 this.CreateUserInfoButton(); } else { // 3.2 已授权,直接获取用户信息 this.GetUserInfo(); // 这里也可以先不获取,留到点击开始游戏按钮再获取,但没必要,先获取后存起来即可 } }, fail = (err) => { Debug.Log("获取用户信息授权情况失败:" + JsonUtility.ToJson(err, true)); } }); } /// <summary> /// 创建用户信息授权点击区域 /// </summary> private void CreateUserInfoButton() { Debug.Log("create userinfo button area"); /** * 方法一:创建用户信息获取按钮,在底部区域创建一个300高度的 透明!!! 区域 * 首次获取会弹出用户授权窗口, 可通过右上角-设置-权限管理用户的授权记录 * 可根据需要设置不同高度,使用屏幕还有其它点击热区的情况 */ // 获取屏幕信息 // var systemInfo = WX.GetSystemInfoSync(); // var canvasWith = (int)(systemInfo.screenWidth * systemInfo.pixelRatio); // var canvasHeight = (int)(systemInfo.screenHeight * systemInfo.pixelRatio); // var buttonHeight = (int)(canvasWith / 1080f * 300f); // 很容易被误导,与其叫按钮,不如叫热区 // WXUserInfoButton btn = WX.CreateUserInfoButton(0, canvasHeight - buttonHeight, canvasWith, buttonHeight, "zh_CN", false); /** * 方法二:创建布满整个屏幕的授权按钮区 */ WXUserInfoButton btn = WX.CreateUserInfoButton(0, 0, Screen.width, Screen.height, "zh_CN", false); // 监听授权区域的点击 btn.OnTap((res) => { Debug.Log("click userinfo btn: " + JsonUtility.ToJson(res, true)); if (res.errCode == 0) { // 用户已允许获取个人信息,返回的 res.userInfo 即为用户信息 Debug.Log("userinfo: " + JsonUtility.ToJson(res.userInfo, true)); // 将用户信息存入成员变量,以待后用 this.userInfo = res.userInfo; // 展示,只是为了测试看到 this.ShowUserInfo(res.userInfo.avatarUrl, res.userInfo.nickName); } else { Debug.Log("用户拒绝获取个人信息"); } // 最后隐藏授权区域,防止阻塞游戏继续 btn.Hide(); Debug.Log("已隐藏热区"); }); } /// <summary> /// 调用Api获取用户信息 /// </summary> private void GetUserInfo() { WX.GetUserInfo(new GetUserInfoOption() { lang = "zh_CN", success = (res) => { Debug.Log("获取用户信息成功(API): " + JsonUtility.ToJson(res.userInfo, true)); // 将用户信息存入成员变量,或存入云端,方便后续使用 this.userInfo = this.ConvertUserInfo(res.userInfo); this.ShowUserInfo(res.userInfo.avatarUrl, res.userInfo.nickName); }, fail = (err) => { Debug.Log("获取用户信息失败(API): " + JsonUtility.ToJson(err, true)); } }); } /// <summary> /// 展示用户信息,对头像、昵称展示的整合 /// ps: 测试用 /// </summary> /// <param name="avatarUrl"></param> /// <param name="nickName"></param> private void ShowUserInfo(string avatarUrl, string nickName) { StartCoroutine(LoadAvatar(avatarUrl)); showNickname(nickName); } /// <summary> /// 展示用户头像 /// ps: 测试用 /// </summary> /// <param name="url"></param> /// <returns></returns> IEnumerator LoadAvatar(string url) { // 加载头像图片 UnityWebRequest request = new UnityWebRequest(url); DownloadHandlerTexture texture = new DownloadHandlerTexture(true); request.downloadHandler = texture; yield return request.SendWebRequest(); if (string.IsNullOrEmpty(request.error)) { avatarTexture = texture.texture; } Sprite sprite = Sprite.Create(avatarTexture, new Rect(0, 0, avatarTexture.width, avatarTexture.height), new Vector2(0.5f, 0.5f)); // 场景中图片对象名称为Avatar Image tempImage = GameObject.Find("Avatar").GetComponent<Image>(); tempImage.sprite = sprite; } /// <summary> /// 展示用户昵称 /// ps: 测试用 /// </summary> /// <param name="name"></param> void showNickname(string name) { // 场景中文本对象名称为Nickname Text nickname = GameObject.Find("Nickname").GetComponent<Text>(); nickname.text = name; } /// <summary> /// 将UserInfo对象转为WXUserInfo /// ps: 不知为何,相同结构要搞两个对象 /// </summary> /// <param name="userInfo"></param> /// <returns></returns> WXUserInfo ConvertUserInfo(UserInfo userInfo) { return new WXUserInfo() { nickName = userInfo.nickName, avatarUrl = userInfo.avatarUrl, country = userInfo.country, province = userInfo.province, city = userInfo.city, language = userInfo.language, gender = (int)userInfo.gender }; } }
注意: 如游戏内需展示头像,最好将头像的域名在微信公众平台内设置为合法域名
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。