一,签到效果
实现效果:
二,实现步骤
2.1 场景搭建
创建 Image 设计为大背景,作为一级父物体,命名为:SignPanel
再 SignPanel 下再创建一个 Image,命名为 Context。作为所有签到内容的父物体,并在其上添加'Grid Layout Group',根据签到内容大小调整其数值即可:
再创建一个 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); } }}
复制代码
评论