【专栏精选】实战:使用LeanCloud上传玩家分数,实现排行榜

本文节选自洪流学堂公众号技术专栏《大话Unity2019》,未经允许不可转载。

洪流学堂公众号回复专栏,查看更多专栏文章。

洪流学堂,让你快人几步。你好,我是郑洪智。

小新:“有了用户登录后,我们总要拿来做点什么事情吧?”
大智:“有了用户登陆信息之后,就可以针对用户来存储他自己的信息了,比如说装备、个人数据、闯关信息等等。”
小新:“是不是类似本地的存档,只不过存到了服务器上?”
大智:“可以这么理解,今天我们来尝试下存储玩家的最高分,并且获取全服的排行榜。”

LeanCloud存储玩家分数

LeanCloud中存储数据的需要用到“对象”,文档在这里:https://leancloud.cn/docs/rest_api.html#hash735965996

如果你熟悉数据库的话,对象类似数据库中的一个表,但是这个对象没有固定的字段,不需要提前标注每个对象上有哪些 key,你你只需要随意设置键值对就可以,后端会保存它。

创建LeanCloud对象

要想使用LeanCloud的对象,可以先在LeanCloud网站的控制台创建对象,也可以不事先创建对象,而通过代码创建。

事先创建的话,可以设置权限:

写入LeanCloud对象

写入LeanCloud对象直接上代码喽:

using System;
using System.Collections;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using Random = UnityEngine.Random;

// 上传分数的Score类,用于序列化成json
[Serializable]
public class Score
{
    public int score;
}

// 用于解析登陆后的token,这个token用来代表已登录的用户
[Serializable]
public class LoginToken{
    public string sessionToken;
}

public class LeanCloudUser : MonoBehaviour
{
    public string AppId;
    public string AppKey;

    public InputField Username;
    public InputField Password;

    private string Token;

    public void Reg()
    {
        var jsonObj = new RegJson()
        {
            username = Username.text,
            password = Password.text
        };
        var json = JsonUtility.ToJson(jsonObj);
        Debug.Log(json);
        StartCoroutine(Request("/users", json));
    }

    public void Login()
    {
        var jsonObj = new RegJson()
        {
            username = Username.text,
            password = Password.text
        };
        var json = JsonUtility.ToJson(jsonObj);
        Debug.Log(json);
        StartCoroutine(Request("/login", json, text =>
        {
            var obj = JsonUtility.FromJson<LoginToken>(text);
            Token = obj.sessionToken;

            UploadMyScore(Random.Range(1, 100));
        }));
    }

    // 重构了请求的类,现在可以更好地适用各种请求
    IEnumerator Request(string path, string json, Action<string> cb = null)
    {

        var url = "https://5jmvfx9e.api.lncld.net/1.1" + path;

        var www = UnityWebRequest.Put(url, json);
        www.method = "POST";
        www.SetRequestHeader("X-LC-Id", AppId);
        www.SetRequestHeader("X-LC-Key", AppKey);
        www.SetRequestHeader("Content-Type", "application/json");
        if (!string.IsNullOrEmpty(Token)) 
            www.SetRequestHeader("X-LC-Session", Token);

        yield return www.SendWebRequest();

        if (www.isHttpError || www.isNetworkError)
        {
            Debug.LogError(www.error);
            Debug.LogError(www.downloadHandler.text);
        }
        else
        {
            Debug.Log(www.downloadHandler.text);
            if (cb != null) cb(www.downloadHandler.text);
        }
    }

    // 上传分数的方法
    private void UploadMyScore(int score)
    {
        var json = JsonUtility.ToJson(new Score(){
            score = score
        });

        StartCoroutine(Request("/classes/Score", json));
    }
}

上面的代码是基于昨天小新重构后的代码又进行了一次重构,现在可以更好地满足不同的请求了。

执行后,就可以在后台看到上传上去的分数了。

LeanCloud排行榜

现在我们有了分数了,怎么获取到排行榜的数据呢?这就需要用到LeanCloud中的对象查询。

文档在这:https://leancloud.cn/docs/rest_api.html#hash860317

排行榜的查询呢,会稍微有一些复杂, 因为我们需要根据玩家的分数进行倒序排列,并取出前10个。

由于取数据使用的HTTP方法是GET,所以需要对代码进行不小的重构,最后代码如下:

using System;
using System.Collections;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using Random = UnityEngine.Random;

// 上传分数的Score类,用于序列化成json
[Serializable]
public class Score
{
    public string username;
    public string userId;
    public int score;
}

// 用于解析登陆后的token,这个token用来代表已登录的用户
[Serializable]
public class UserInfo{
    public string sessionToken;
    public string username;
    public string objectId;
}

public class LeanCloudUser : MonoBehaviour
{
    public string AppId;
    public string AppKey;

    public InputField Username;
    public InputField Password;

    private UserInfo User;

    public void Reg()
    {
        var jsonObj = new RegJson()
        {
            username = Username.text,
            password = Password.text
        };
        var json = JsonUtility.ToJson(jsonObj);
        Debug.Log(json);
        StartCoroutine(Request("/users", "POST", json));
    }

    public void Login()
    {
        var jsonObj = new RegJson()
        {
            username = Username.text,
            password = Password.text
        };
        var json = JsonUtility.ToJson(jsonObj);
        Debug.Log(json);
        StartCoroutine(Request("/login", "POST", json, text =>
        {
            var obj = JsonUtility.FromJson<UserInfo>(text);
            User = obj;

            UploadMyScore(Random.Range(1, 100));
        }));
    }

    // 重构了请求的类,现在可以更好地适用各种请求
    IEnumerator Request(string path, string method = "POST", string data = "", Action<string> cb = null)
    {

        var url = "https://5jmvfx9e.api.lncld.net/1.1" + path;

        var downloadHandler = new DownloadHandlerBuffer();
        UploadHandlerRaw uploadHandler = null;
        if (!string.IsNullOrEmpty(data))
         uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(data));
        var www = new UnityWebRequest(url, method, downloadHandler, uploadHandler);
        www.SetRequestHeader("X-LC-Id", AppId);
        www.SetRequestHeader("X-LC-Key", AppKey);
        www.SetRequestHeader("Content-Type", "application/json");


        yield return www.SendWebRequest();

        if (www.isHttpError || www.isNetworkError)
        {
            Debug.LogError(www.error);
            Debug.LogError(www.downloadHandler.text);
        }
        else
        {
            Debug.Log(www.downloadHandler.text);
            if (cb != null) cb(www.downloadHandler.text);
        }
    }

    // 上传分数的方法
    private void UploadMyScore(int score)
    {
        var json = JsonUtility.ToJson(new Score(){
            score = score,
            username = User.username,
            userId = User.objectId
        });

        StartCoroutine(Request("/classes/Score", "POST", json, _=>{
            GetLeaderboard();
        }));
    }

    public void GetLeaderboard(){
        var path = "/classes/Score?";
        path += "order=-score&limit=10";

        StartCoroutine(Request(path, "GET"));
    }
}

在这由于取出排行榜中的数据要用GET,终于我们没办法使用取巧的请求方式了,老老实实地改回来正常的请求方法。

总结

小新:“其实代码看下来,请求的方式都是类似的,比较重要的是先好好看懂LeanCloud的文档,然后构造相应的请求就可以了。”
大智:“没错,读文档的能力是很重要的,以后写出一份好文档的能力是更重要的。”

思考题

大智:“取到排行榜的数据以后,看看能不能显示到UI上面?”
小新:“好嘞!”
大智:“收获别忘了分享出来!也别忘了分享给你学Unity的朋友,也许能够帮到他。”

推荐阅读

《大话Unity2019》,大智带小新学Unity2019的有趣经历,让你学Unity更简单。

发布了138 篇原创文章 · 获赞 72 · 访问量 29万+

猜你喜欢

转载自blog.csdn.net/zhenghongzhi6/article/details/91362256