Unity 之 模拟王者荣耀七日签到系统

简介: 做一个模拟王者荣耀的签到系统,七日签到不可补签,下周自动重置。

@TOC

一,效果图

不带补签版本:
1.2


二,制作思路

使用切换图片背景颜色的方式,进行状态转换【灰色:已签到;蓝色:可签到;白色:未签到】

主要逻辑:

  • 每次签到时保存一个签到日期,用于判断今日是否签到;
  • 根据是否已签到显示UI界面,提示信息等;
  • 未签到时,点击按钮,进行签到(保存签到日期,发放奖励,维护UI显示等);
  • 另外,还需要进行新的一周签到开始的逻辑重置;

上述逻辑,基本上模拟了王者荣耀的签到面板功能了,下面我们开始实现吧。


三,场景搭建

3.1
Demo场景搭建如上图:(没有资源有点丑~)

  1. 制作一个签到按钮(一个Image,下面放了一个Image和一个Text)
  2. 复制六份(单独创建一个空物体,作为它们的父物体)
  3. 创建一个文本(随便放在哪里,显示提示信息用的)

四,代码实现

就是按上面说的实现的逻辑,代码中注释也写的很详细了,全部代码如下:

using System;
using UnityEngine;
using UnityEngine.UI;

public class SingInDemo : MonoBehaviour
{
    // 签到按钮的父物体
    public Transform WeekParent;
    
    // 提示文字
    public Text HintText;
    
    // 上次签到时间 -- 和今天时间对比,确定是否今日已签到
    private readonly string prefsLastCheckTime = "prefsLastCheckTime";
    
    // 本周已签到几天 例:2 --> 表示周一,周二已签到
    private readonly string prefsWeekAlreadyDay = "prefsWeekAlreadyDay";

    // 今天周几
    private int weekToday;
    // 本周签到了几天
    private int alreadyDay;

    void Start()
    {
        //PlayerPrefs.DeleteAll();
        weekToday = GetDateWeek(DateTime.Now.ToString());

        AlreadyByWeek();
        // 查看本周签到了几天了
        alreadyDay = PlayerPrefs.GetInt(prefsWeekAlreadyDay);

        for (int i = 0; i < WeekParent.childCount; i++)
        {
            GameObject go = WeekParent.GetChild(i).gameObject;
            // 监听按钮点击
            go.GetComponent<Button>().onClick.AddListener(() => { OnClickSingInBtn(go); });

            // 标识是否已签到
            bool isAlready = alreadyDay > i;
            go.GetComponent<Image>().color = isAlready ? Color.gray : Color.white;
            go.transform.GetChild(1).gameObject.SetActive(isAlready);
        }

        // 今天还没签到
        if (!AlreadyByToDay())
        {
            WeekParent.GetChild(alreadyDay).GetComponent<Image>().color = Color.cyan;
        }

        // 显示提示信息
        ShowHintText(alreadyDay);
    }

    // 点击签到按钮
    private void OnClickSingInBtn(GameObject go)
    {
        // 点了星期 ?签到按钮
        string week = go.name.Split('_')[1];
        Debug.Log("点击了..." + go.name + "按钮, 是周" + week);

        // 可签到
        alreadyDay = PlayerPrefs.GetInt(prefsWeekAlreadyDay);
        if (!AlreadyByToDay()) 
        {
            Debug.Log("签到成功,签到成功的是,是周" + week);
            go.transform.GetChild(1).gameObject.SetActive(true);
            go.transform.GetComponent<Image>().color = Color.gray;
            PlayerPrefs.SetString(prefsLastCheckTime, DateTime.Now.ToString("d"));
            PlayerPrefs.SetInt(prefsWeekAlreadyDay, ++alreadyDay);

            // 显示提示信息
            ShowHintText(alreadyDay);
            Debug.Log("~~~~~~~~~~~~ 签到成功的奖励还没写哦 ~~~~~~~~~~~~");
        }
        else
        {
            Debug.Log("今日已签到,不能重复签到哦~");
        }
    }

    /// <summary>
    /// 本周是是否已签到 -- 计算上次签到时间 是不是在本周内
    /// </summary>
    void AlreadyByWeek()
    {
        if (!PlayerPrefs.HasKey(prefsLastCheckTime)) return;
        
        // 本周周一
        string startWeek = GetMondayDate(DateTime.Now).ToString("d");
        // 上次签到时间的周一
        DateTime dtmE = DateTime.Parse(PlayerPrefs.GetString(PlayerKey.SigninLastCheckTime.ToString()));
        string lastWeek =  GetMondayDate(dtmE).ToString("d");

        // 上次签到周不是本周 && 今日未签到 
        if (startWeek != lastWeek && !AlreadyByToDay())
        {
            Debug.Log("新的一周开始,重置所有签到信息...");
            PlayerPrefs.DeleteKey(prefsLastCheckTime);
            PlayerPrefs.DeleteKey(prefsWeekAlreadyDay);
        }
    }

    /// <summary>
    /// 今天是否已签到
    /// </summary>
    /// <returns></returns>
    bool AlreadyByToDay()
    {
        string today = DateTime.Now.ToString("d");
        return PlayerPrefs.GetString(prefsLastCheckTime) == today;
    }
    
    /// <summary>
    /// 返回传入日期是周几
    /// </summary>
    /// <param name="strYMD"></param>
    /// <returns></returns>
    int GetDateWeek(string strYMD)
    {
        int week = Convert.ToInt32(Convert.ToDateTime(strYMD).DayOfWeek);
        // 0:表示是周日
        return week != 0 ? week : 7;
    }

    // 提示文本
    void ShowHintText(int alreadyDay)
    {
        if (!AlreadyByToDay())
        {
            HintText.text = "今日未签到, 本周已签到" + alreadyDay + " 天";
        }
        else
        {
            HintText.text = "今日已签到,本周已签: " + alreadyDay + " 天, 可补签" +  (weekToday - alreadyDay) + " 天";;
        }
    }
    /// <summary>
    /// 计算某日起始日期(礼拜一的日期)
    /// </summary>
    /// <param name="someDate">该周中任意一天</param>
    /// <returns>返回礼拜一日期,后面的具体时、分、秒和传入值相等</returns>
    DateTime GetMondayDate(DateTime someDate)
    {
        int i = someDate.DayOfWeek - DayOfWeek.Monday;
        if (i == -1) i = 6;// i值 > = 0 ,因为枚举原因,Sunday排在最前,此时Sunday-Monday=-1,必须+7=6。
        TimeSpan ts = new TimeSpan(i, 0, 0, 0);
        return someDate.Subtract(ts);
    }
}

五,拓展补签版本

顺着上面的实现思路,很容易就是可以实现一个带补签的版本:

看下效果图:
1.2
其实就是把上面代码校验今天是否已签到的地方修改为是否可补签,然后添加一个补签逻辑就可以了。

场景搭建还是和上面一样,代码实现如下:

using System;
using UnityEngine;
using UnityEngine.UI;

public class SingInDemo : MonoBehaviour
{
    // 签到按钮的父物体
    public Transform WeekParent;
    
    // 提示文字
    public Text HintText;
    
    // 上次签到时间 -- 和今天时间对比,确定是否今日已签到
    private readonly string prefsLastCheckTime = "prefsLastCheckTime";
    
    // 本周已签到几天 例:2 --> 表示周一,周二已签到
    private readonly string prefsWeekAlreadyDay = "prefsWeekAlreadyDay";

    // 今天周几
    private int weekToday;
    // 本周签到了几天
    private int alreadyDay;

    void Start()
    {
        //PlayerPrefs.DeleteAll();
        weekToday = GetDateWeek(DateTime.Now.ToString());

        AlreadyByWeek();
        // 查看本周签到了几天了
        alreadyDay = PlayerPrefs.GetInt(prefsWeekAlreadyDay);

        for (int i = 0; i < WeekParent.childCount; i++)
        {
            GameObject go = WeekParent.GetChild(i).gameObject;
            // 监听按钮点击
            go.GetComponent<Button>().onClick.AddListener(() => { OnClickSingInBtn(go); });

            // 标识是否已签到
            bool isAlready = alreadyDay > i;
            go.GetComponent<Image>().color = isAlready ? Color.gray : Color.white;
            go.transform.GetChild(1).gameObject.SetActive(isAlready);
        }

        // 今天还没签到
        if (weekToday - alreadyDay > 0)  //(!AlreadyByToDay()) // todo...不可补签使用 
        {
            WeekParent.GetChild(alreadyDay).GetComponent<Image>().color = Color.cyan;
        }

        // 显示提示信息
        ShowHintText(alreadyDay);
    }

    // 点击签到按钮
    private void OnClickSingInBtn(GameObject go)
    {
        // 点了星期 ?签到按钮
        string week = go.name.Split('_')[1];
        Debug.Log("点击了..." + go.name + "按钮, 是周" + week);

        // 可签到
        alreadyDay = PlayerPrefs.GetInt(prefsWeekAlreadyDay);
        if (weekToday - alreadyDay > 0)  //(!AlreadyByToDay()) // todo...不可补签使用 
        {
            Debug.Log("签到成功,签到成功的是,是周" + week);
            go.transform.GetChild(1).gameObject.SetActive(true);
            go.transform.GetComponent<Image>().color = Color.gray;
            PlayerPrefs.SetString(prefsLastCheckTime, DateTime.Now.ToString("d"));
            PlayerPrefs.SetInt(prefsWeekAlreadyDay, ++alreadyDay);

            // 显示提示信息
            ShowHintText(alreadyDay);

            #region 补签逻辑 -- todo..不需补签直接删掉即可
            if (AlreadyByToDay())
            {
                Debug.Log("--- 补签成功, 这是本周第" + alreadyDay + "次签到 ---");
            }
            else
            {
                Debug.Log("+++ 签到成功, 这是本周第" + alreadyDay + "次签到 +++");
            }

            // 可补签~,添加可点击标识
            if (weekToday - alreadyDay > 0)
            {
                WeekParent.GetChild(alreadyDay).GetComponent<Image>().color = Color.cyan;
            }
            #endregion
            
            Debug.Log("~~~~~~~~~~~~ 签到成功的奖励还没写哦 ~~~~~~~~~~~~");
        }
        else
        {
            Debug.Log("今日已签到,不能重复签到哦~");
        }
    }

    /// <summary>
    /// 本周是是否已签到 -- 计算上次签到时间 是不是在本周内
    /// </summary>
    void AlreadyByWeek()
    {
        if (!PlayerPrefs.HasKey(prefsLastCheckTime)) return;
        
       // 本周周一
        string startWeek = GetMondayDate(DateTime.Now).ToString("d");
        // 上次签到时间的周一
        DateTime dtmE = DateTime.Parse(PlayerPrefs.GetString(PlayerKey.SigninLastCheckTime.ToString()));
        string lastWeek =  GetMondayDate(dtmE).ToString("d");

        // 上次签到周不是本周 && 今日未签到 
        if (startWeek != lastWeek && !AlreadyByToDay())
        {
            Debug.Log("新的一周开始,重置所有签到信息...");
            PlayerPrefs.DeleteKey(prefsLastCheckTime);
            PlayerPrefs.DeleteKey(prefsWeekAlreadyDay);
        }
    }

    /// <summary>
    /// 今天是否已签到
    /// </summary>
    /// <returns></returns>
    bool AlreadyByToDay()
    {
        string today = DateTime.Now.ToString("d");
        return PlayerPrefs.GetString(prefsLastCheckTime) == today;
    }
    
    /// <summary>
    /// 返回传入日期是周几
    /// </summary>
    /// <param name="strYMD"></param>
    /// <returns></returns>
    int GetDateWeek(string strYMD)
    {
        int week = Convert.ToInt32(Convert.ToDateTime(strYMD).DayOfWeek);
        // 0:表示是周日
        return week != 0 ? week : 7;
    }

    // 提示文本
    void ShowHintText(int alreadyDay)
    {
        if (!AlreadyByToDay())
        {
            HintText.text = "今日未签到, 本周已签到" + alreadyDay + " 天";
        }
        else
        {
            HintText.text = "今日已签到,本周已签: " + alreadyDay + " 天, 可补签" +  (weekToday - alreadyDay) + " 天";;
        }
    }

    /// <summary>
    /// 计算某日起始日期(礼拜一的日期)
    /// </summary>
    /// <param name="someDate">该周中任意一天</param>
    /// <returns>返回礼拜一日期,后面的具体时、分、秒和传入值相等</returns>
    DateTime GetMondayDate(DateTime someDate)
    {
        int i = someDate.DayOfWeek - DayOfWeek.Monday;
        if (i == -1) i = 6;// i值 > = 0 ,因为枚举原因,Sunday排在最前,此时Sunday-Monday=-1,必须+7=6。
        TimeSpan ts = new TimeSpan(i, 0, 0, 0);
        return someDate.Subtract(ts);
    }
}
相关文章
|
4月前
|
编解码 前端开发 人机交互
【Unity 3D】UI系统中UGUI各个组件的详细讲解(附源码 超详细)
【Unity 3D】UI系统中UGUI各个组件的详细讲解(附源码 超详细)
89 0
|
4月前
|
人工智能 算法 图形学
Unity 动画系统基本概念
Unity 动画系统基本概念
|
10月前
|
图形学
unity-初级动画系统
unity-初级动画系统
71 0
|
Web App开发 开发工具 图形学
|
图形学 数据安全/隐私保护
还在用Unity开发游戏?那你就out了,试试用Unity做一个答题系统吧
大家都支持Unity是用来做游戏开发,比如说做2D游戏、3D游戏,或者工业虚拟仿真软件的开发。 其他Unity可以做的有很多,比如答题系统。 本篇就介绍答题系统的开发 这个答题系统,可以从文本文档中提取题目和分数,然后绑定到UI上,在答题的过程中,自动判断分数,自动判断正确率。 目的是实现一个可快速导入到项目中使用的小模块。
|
数据可视化 图形学
Unity Mecanim 动画系统简介
Unity Mecanim 动画系统简介
93 0
Unity Mecanim 动画系统简介
|
图形学
|
存储 图形学
Unity实战之王者荣耀段位计算
Unity实现王者荣耀段位计算
Unity实战之王者荣耀段位计算
|
API 图形学 Android开发
创作 【Unity使用UGUI实现王者荣耀UI界面(四)】游戏开始界面
创作 【Unity使用UGUI实现王者荣耀UI界面(四)】游戏开始界面
393 0
创作 【Unity使用UGUI实现王者荣耀UI界面(四)】游戏开始界面
|
API 图形学 Python
【Unity使用UGUI实现王者荣耀UI界面(三)】登录界面以及加载界面优化
【Unity使用UGUI实现王者荣耀UI界面(三)】登录界面以及加载界面优化
240 0
【Unity使用UGUI实现王者荣耀UI界面(三)】登录界面以及加载界面优化