• Unity 之 月签到累计签到代码实现(ScriptableObject应用 | DoTween入场动画)


    一,签到效果

    实现效果:


    二,实现步骤

    2.1 场景搭建

    1. 创建Image设计为大背景,作为一级父物体,命名为:SignPanel
    2. 再SignPanel下再创建一个Image,命名为Context。作为所有签到内容的父物体,并在其上添加’Grid Layout Group’,根据签到内容大小调整其数值即可:
    3. 再创建一个Image,作为签到内容的背景板,在其下一次创建:Image,Text,Button,Image;分别作为每个签到内容的奖励图片,奖励数量,可领取按钮,已领取图片。此物体将作为签到内容的克隆体。

    最终搭建场景如下:


    2.2 创建配置

    通过ScriptableObject做一个配置文件,里面存储每日签到的奖励类型和数量。创建代码命名为MonthSignAwardData,继承修改为ScriptableObject,并给其添加CreateAssetMenu编辑器拓展。

    完整代码如下:

    using System;
    using System.Collections.Generic;
    using UnityEngine;
    
    [CreateAssetMenu(fileName = "MonthSignAwardData", menuName = "GameData/MonthSignAwardData", order = 1)]
    public class MonthSignAwardData : ScriptableObject
    {
        public List<AwardItem>  awardDataList = new List<AwardItem>();
    }
    
    [Serializable]
    public class AwardItem
    {
        /// 
        /// 奖励类型 0:金币,1:钻石
        /// 
        public CurrencyType awardType;
        
        // 奖励数量
        public int awardCount;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    创建完成此代码就可以在文件中右键 --> Create --> GameData --> MonthSignAwardData。创建出一个MonthSignAwardData配置文件,然后手动编辑一下奖励内容就可以了。

    PS:我这里为了方便演示后面加载,将配置文件直接存储到Resources文件夹下了。


    2.3 编写代码

    逻辑也比较简单,通过PlayerPrefs存储一个上次签到日期,存储一个上传签到索引。然后通过上次签到日期和本地日期比较判断今日是否已签到。

    完整逻辑如下:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using DG.Tweening;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class MonthSignIn : MonoBehaviour
    {
        [Header("奖励图")]
        [SerializeField] private Sprite[] Spr_AwardSprites;
        
        [Header("模版")]
        [SerializeField] private GameObject Obj_Item;
    
        [Header("内容父物体")]
        [SerializeField] private Transform Tran_Context;
        
        [Header("关闭按钮")]
        [SerializeField] private Button Btn_Close;
    
        [Header("内容列表")]
        [SerializeField] private List<SignItem> signList;
    
        // 配置文件
        private MonthSignAwardData _signAwardData;
        
        // 上次签到索引
        private int LastSignIndex
        {
            get { return PlayerPrefs.GetInt("CzhenyaGameDataLastSignIndex", 0); }
            set { PlayerPrefs.SetInt("CzhenyaGameDataLastSignIndex", value); }
        }
        // 上次签到日期
        private string LastSignDate
        {
            get { return PlayerPrefs.GetString("CzhenyaGameDataLastSignDate", "yy-MM-dd"); }
            set { PlayerPrefs.SetString("CzhenyaGameDataLastSignDate", value); }
        }
    
        void Start()
        {
            Obj_Item.gameObject.SetActive(false);
            _signAwardData = Resources.Load<MonthSignAwardData>("MonthSignAwardData");
            
            signList = new List<SignItem>();
            for (int i = 0; i < _signAwardData.awardDataList.Count; i++)
            {
                Transform itemTrans = Instantiate(Obj_Item, Tran_Context).transform;
                itemTrans.gameObject.SetActive(true);
                SignItem signItem = new SignItem();
                signItem.Img_Context = itemTrans.GetChild(0).GetComponent<Image>();
                signItem.Text_ContextNum = itemTrans.GetChild(1).GetComponent<Text>();
                signItem.Btn_Receive = itemTrans.GetChild(2).GetComponent<Button>();
                signItem.Obj_Mask = itemTrans.GetChild(3).gameObject;
                
                signItem.Btn_Receive.onClick.AddListener(OnClickReceive);
                int awardCount = _signAwardData.awardDataList[i].awardCount;
                int spriteIndex = (int)_signAwardData.awardDataList[i].awardType;
                signItem.Img_Context.sprite = Spr_AwardSprites[spriteIndex];
                //signItem.Img_Context.SetNativeSize();
                signItem.Text_ContextNum.text = "x" + awardCount;
                
                signList.Add(signItem);
            }
    
            Btn_Close.onClick.AddListener(OnClickClose);
            UpdateSignStatus();
        }
    
        /// 
        /// 更新签到状态
        /// 
        void UpdateSignStatus()
        {
            for (int i = 0; i < signList.Count; i++)
            {
                signList[i].Btn_Receive.gameObject.SetActive(false);
                signList[i].Obj_Mask.SetActive(i < LastSignIndex);
            }
            // 今天没签
            if (!LastSignDate.Contains(DateTime.Today.ToString("MM/dd/yyyy")))
            {
                signList[LastSignIndex].Btn_Receive.gameObject.SetActive(true);
            }
        }
    
        /// 
        /// 点击签到 -- 领取签到奖励
        /// 
        void OnClickReceive()
        {
            int curIndex = LastSignIndex;
            // todo... 恭喜获得
            Debug.Log("当前领取id:" + curIndex);
    
            if (LastSignIndex >= 27)
            {
                LastSignIndex = 0;
            }
            else
            {
                LastSignIndex++;
            }
    
            LastSignDate = DateTime.Today.ToString("MM/dd/yyyy");
            UpdateSignStatus();
        }
    
        /// 
        /// 关闭面板
        /// 
        void OnClickClose()
        {
            gameObject.SetActive(false);
        }
        
    }
    
    // 签到内容
    public class SignItem
    {
        public Image Img_Context;
        public Text Text_ContextNum;
        public Button Btn_Receive;
        public GameObject Obj_Mask;
    }
    
    public enum CurrencyType
    {
        /// 
        /// 金币
        /// 
        Gold,
    
        /// 
        /// 钻石
        /// 
        Gam,
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140

    将上面代码挂载到SignPanel,然后将公开变量挨个赋值:


    三,拓展:入场动画

    将下面代码添加到MonthSignIn类中,即可实现开篇看到的入场动画效果:

    private void OnEnable()
    {
        PlayDoAni();
    }
    // 播放进入动画
    public void PlayDoAni()
    {
        StartCoroutine(DoAni());
    }
    
    // 入场动画
    IEnumerator DoAni()
    {
        for (int i = 1; i < Tran_Context.childCount; i++)
        {
            Tran_Context.GetChild(i).gameObject.SetActive(false);
        }
        for (int i = 1; i < Tran_Context.childCount; i++)
        {
            Tran_Context.GetChild(i).gameObject.SetActive(true);
            Tran_Context.GetChild(i).transform.localScale = Vector3.zero;
            Tran_Context.GetChild(i).DOScale(Vector3.one, 0.2f).SetEase(Ease.OutBack);
            if (i % 3 == 0)
            {
                yield return new WaitForSeconds(0.06f);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    源码和步骤都在上面分享过了,若还有什么不明白的,可以点击链接下载,积分不够的童鞋关注下方卡片公号​,回复:“月签到” 即可获得Demo源码~

  • 相关阅读:
    Java - AQS-CountDownLatch实现类(二)
    导航栏参考代码
    计算机毕业设计Java派大星水产商城(源代码+数据库+系统+lw文档)
    QT:使用堆叠窗口、标签、下拉条
    非对称加密(RSA)详解
    Java学习笔记42——方法引用
    前端进阶特训营-TDD制造rollup-0
    泛型编程——模板【C++】
    【个人学习笔记】概率论与数理统计知识梳理【六】
    JavaWeb知识梳理(后端部分)
  • 原文地址:https://blog.csdn.net/Czhenya/article/details/127870292