上一篇中我们实现用本地文件实现了持久化类的保存,当然小型数据用PlayerPrefs存储,或者采用XML服务器持久化也行。因为我涉及的角色类和玩家类数据比较多,加上项目要求尽量少与服务器交互,所以采用了本地持久化。废话不多说,进入主题
一、应用场景
项目要实现这么一个每日登陆的功能,设计如下:
我们假设每天9点刷新登陆奖励,中断一天则从第一天开始:
初步设想是每日登陆奖励必须有网的情况下才能领取,通过服务器逻辑验证上一次领取时间和登陆时间,产生对应的奖励界面。
至于领取时间可以采用服务器自动刷新和玩家手动刷新,这里我选择了手动刷新。
注意,最好不要采用本地时间为基准。
二、设计思路
玩家持久化类中增加一个领取奖励时间变量,规则如下:
在每次登陆游戏联网的时候得到服务器的标准网络时间,和上一次的领取奖励时间进行逻辑判断。
有以下三种情况:
领取奖励时间为null:
领取奖励时间和联网验证时间在同一天:
领取奖励时间和联网验证时间不在同一天:
逻辑图如下:
至于领取时间刷新,则如下图所示有两种情况:
一、服务器判断逻辑之后自动给客户端刷新
二、客户端手动刷新
三、核心代码
//进行联网验证
if (DebugUtils.HasConnection() && Globals.Me != null){ Globals.NetWorkAvailable = true; //请求服务器刷新 StartCoroutine(UpdateLoginTime());}public IEnumerator UpdateLoginTime(){ Debug.Log("privious time is " + Globals.Me.LoginDateTime); if (!Globals.NetWorkAvailable) yield break; WWW www = new WWW(GameUrl.Time_Url); yield return www; //有错误 #region if (www.error != null) { Utils.WriteLog("UpdateLoginTime" + www.error); MsgBox.Show("亲 网络有问题哦"); Globals.NetWorkAvailable = false; } #endregion else { //解析网络时间 #region string[] tempArray = www.text.Split(';'); for (int i = 0; i < tempArray.Length; i++) { tempArray[i] = tempArray[i].Replace("\r\n", ""); } string year = tempArray[1].Split('=')[1]; string month = tempArray[2].Split('=')[1]; string day = tempArray[3].Split('=')[1]; string hour = tempArray[5].Split('=')[1]; string minite = tempArray[6].Split('=')[1]; string second = tempArray[7].Split('=')[1]; DateTime tmp = DateTime.Parse(year + "-" + month + "-" + day + " " + hour + ":" + minite + ":" + second); #endregion Debug.Log("update time" + tmp); //第一次更新 //这里是服务器逻辑判断 #region if (Globals.Me.LoginDateTime == null) { //调用第一天第一次奖励 if (!PlayerPrefs.HasKey("Reward_Level")){ PlayerPrefs.SetInt("Reward_Level", (int)(Login_Kind.FirstDay)); Debug.Log("first" + PlayerPrefs.GetInt("Reward_Level")); } else { PlayerPrefs.SetInt("Reward_Level", (int)(Login_Kind.FirstDay)); Debug.Log("first" + PlayerPrefs.GetInt("Reward_Level")); } Create_Login_Reward(tmp); } #endregion //不是第一次 else { //不是同一天更新 #region if (!isSameDay(tmp)) { //是连续更新 #region if (isContinue(tmp)) { PlayerPrefs.SetInt("Reward_Level", ((PlayerPrefs.GetInt("Reward_Level") + 1) % 7)); Debug.Log("then" + PlayerPrefs.GetInt("Reward_Level")); } #endregion //不是连续更新 #region else { //调用第一天奖励 PlayerPrefs.SetInt("Reward_Level", (int)(Login_Kind.FirstDay)); Debug.Log("Reset" + PlayerPrefs.GetInt("Reward_Level")); } #endregion Create_Login_Reward(tmp); } #endregion //同一天 #region else { Create_Normal(); } #endregion } }}
//根据联网的服务器逻辑产生对应的奖励列表
//satisfy update reward condition //called by other public void Update_Reward(DateTime updatetime) { #region foreach (Transform child in transform) { if (child.name.Contains("_")) { int Reward_Level = PlayerPrefs.GetInt("Reward_Level"); //check Reward_Level day #region if (int.Parse(child.name.Split('_')[0]) == Reward_Level) { child.GetChild(0).active = true; Set_Refresh(int.Parse(child.name.Split('_')[1]) * 1000, updatetime); } else { child.GetChild(0).active = false; } #endregion //yellow <= Reward_Level //blue > Reward_Level #region if (int.Parse(child.name.Split('_')[0]) <= Reward_Level) { //yellow child.GetComponent().OnMouseDown(); } else { //blue child.GetComponent ().OnMouseUpAsButton(); } #endregion } } #endregion } public void Set_Refresh(int Add_Number,DateTime RefreshDateTime) { UI_Get_LoginReword tmp = transform.Find("Get").GetComponent (); tmp.Add_Number = Add_Number; tmp.RefreshDateTime = RefreshDateTime; }
//采用手动刷新 这里是按下领取奖励按钮之后
public void OnMouseUpAsButton(){ //print("you enter is " + transform.name); base.OnMouseUpAsButton(); if (Add_Number != 0 && RefreshDateTime!=DateTime.MinValue) { //print(Add_Number + "add is "); //Globals.Me.LoginDateTime = new Nullable(currentTime); Globals.Me.LoginDateTime = RefreshDateTime; print("RefreshDateTime is " + Globals.Me.LoginDateTime); Globals.Me.Gold_Number += Add_Number; }}
四、总结
这里把服务器逻辑放在本地,其实应该放在服务器上的,后期可以考虑采用服务器判断。