写点什么

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

作者:陈言必行
  • 2023-04-19
    辽宁
  • 本文字数:3600 字

    阅读完需:约 12 分钟

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

一,签到效果

实现效果:




二,实现步骤

2.1 场景搭建

  1. 创建 Image 设计为大背景,作为一级父物体,命名为:SignPanel

  2. 再 SignPanel 下再创建一个 Image,命名为 Context。作为所有签到内容的父物体,并在其上添加'Grid Layout Group',根据签到内容大小调整其数值即可:


  1. 再创建一个 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{    /// <summary>    /// 奖励类型 0:金币,1:钻石    /// </summary>    public CurrencyType awardType;        // 奖励数量    public int awardCount;}
复制代码

创建完成此代码就可以在文件中右键 --> 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();    }
    /// <summary>    /// 更新签到状态    /// </summary>    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);        }    }
    /// <summary>    /// 点击签到 -- 领取签到奖励    /// </summary>    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();    }
    /// <summary>    /// 关闭面板    /// </summary>    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{    /// <summary>    /// 金币    /// </summary>    Gold,
    /// <summary>    /// 钻石    /// </summary>    Gam,}
复制代码

将上面代码挂载到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);        }    }}
复制代码


发布于: 刚刚阅读数: 5
用户头像

陈言必行

关注

公号:开发同学留步 2019-03-12 加入

我是一个从事Unity游戏开发攻城狮,InfoQ&阿里云签约博主,CSDN博客专家,U3D论坛版主,6年开发经验,助你日常不加班。⽂章皆为从零到⼀的⼊⻔级教程,也有很多⼯作中遇到的问题解析。

评论

发布
暂无评论
Unity 之 月签到累计签到代码实现(ScriptableObject应用 | DoTween入场动画)_Unity_陈言必行_InfoQ写作社区