Unity开发微信小游戏获取用户信息

前言

Unity开发微信小游戏过程中,想要获取用户信息,遇到了许多坑位,这里记录一下

待实现效果

  • 初次进入游戏,询问是否同意隐私协议
  • 接着查询用户信息授权情况
    • 已授权,直接获取用户信息
    • 未授权,创建授权按钮

实现步骤

以下步骤仅提供参考
有些细则可在官方文档官方Demo查看,可能隐藏较深,需耐心翻找,并且很多适配API的文档需在源码注释里找

设置

用户信息属于敏感数据,想获取需要授权,而想授权成功则需要同意隐私协议。所以,需要到微信公众号平台设置隐私协议

PS:坑位一,这些在官方文档几乎没提到,不然就是隐藏极深

  • 登录微信公众平台
  • 点击设置 > 服务内容声明
    隐私协议设置

Unity操作

  • 在场景里新建一个空对象,这里取名为Loader
  • 新建一个脚本,绑定给Loader
  • 在场景里新建一个按钮,文本设置为Start Game,用于表示开始游戏
  • 为按钮的点击事件绑定Loader脚本的函数
    button
  • 最终界面如下
    scene
    其中,按钮作用主要是为了引导用户点击授权区域

脚本编写

以下是脚本内容,具体可看代码注释
大致的步骤是

  • 初始化SDK
  • 询问隐私协议授权情况
    • 未授权则弹出询问隐私协议
  • 询问用户信息授权情况
    • 已授权,直接获取用户信息
    • 未授权,创建授权点击区域

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
        };
    }
}

注意: 如游戏内需展示头像,最好将头像的域名在微信公众平台内设置为合法域名

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值