Unity 离线建造系统

简介:

Unity 离线建造系统

很多游戏,特别是养成类手游,都会有自己独特的建造系统,一个建造装置的状态循环或者说生命周期一般是这样的:

1.准备建造,设置各项资源的投入等

2.等待一段倒计时,正在建造中

3.建造结束,选择是否收取资源

大体上,可以将建造盒子分为以下三种状态,每一个状态的逻辑和显示的页面不同:

1 public enum BuildBoxState
2 {
3 Start,
4 Doing,
5 Complete
6 }

1 private void ShiftState(BuildBoxState state)
2 {
3 switch (state)
4 {
5 case BuildBoxState.Start:
6 Start.SetActive(true);
7 Doing.SetActive(false);
8 Complete.SetActive(false);
9
10 ResetResCount();
11 break;
12 case BuildBoxState.Doing:
13 Start.SetActive(false);
14 Doing.SetActive(true);
15 Complete.SetActive(false);
16
17 StartCoroutine(ShowBuildTime());
18 break;
19 case BuildBoxState.Complete:
20 Start.SetActive(false);
21 Doing.SetActive(false);
22 Complete.SetActive(true);
23
24 break;
25 }
26 CurState = state;
27 }

这里值得思考的并非是状态的切换或者基础的按钮侦听,视图资源更新等。

如何在离线一段时间后重新获取目前对应建造盒子所处的状态才是重点;并且如果处于建造中状态的话,还应该能正确的显示剩余时间的倒计时。

一个非常常见的想法是,在建造开始时记录一份开始建造的时间数据给服务器或存在本地离线数据中,当下一次再登录时读取当前系统的时间,并通过总共需要的建造时长来计算剩余时间。

但假如总共需要的建造时长与当时投入的资源类型和量都有关系,这时就需要至少额外记载一类数据来进行计算。那么,有没有方法仅通过一个数据得到剩余时长呢?

答案是,不记录开始建造的时刻,改为记录拟定建造完成的时刻。

如此一来,每次离线登录后,只需要干两件事既可以判断出所有状态视图:

1.是否存在该建造盒子ID对应的拟定建造完成时刻的数据,如果不存在,一定是处于准备状态,即Start状态。

2.如果存在,对比当前系统时刻与拟定建造完成时刻的数据大小,大于等于则处于完成状态,小于则依然在建造中,并按秒显示差值更新。

记录的时刻如下:

1 public string BuildCompleteTime
2 {
3 get
4 {
5 if (PlayerPrefs.HasKey(ID.ToString()))
6 return PlayerPrefs.GetString(ID.ToString());
7 return S_Null;
8 }
9 set
10 {
11 PlayerPrefs.SetString(ID.ToString(), value);
12 PlayerPrefs.Save();
13 }
14 }

每次开始时,只需要判断这个数据是否存在:

1 protected override void InitState()
2 {
3 View = HudView as BuildBoxView;
4 if (BuildCompleteTime == S_Null)
5 {
6 ShiftState(BuildBoxState.Start);
7 }
8 else
9 {
10 ShiftState(BuildBoxState.Doing);
11 }
12 }

通过建造中的时刻关系自动判断是否完成:

1 IEnumerator ShowBuildTime()
2 {
3 var ct = GetCompleteTime();
4 if (CheckBuildCompleted(ct))
5 {
6 ShiftState(BuildBoxState.Complete);
7 yield break;
8 }
9 else
10 {
11 for (; ; )
12 {
13 View.SetTime(CalNeedTime(ct));
14 yield return new WaitForSeconds(1);
15 }
16 }
17 }

当建造完成点击收取资源时,切换为准备状态的同时,自动清空拟定建造完成时刻的数据记录:

1 private void OnClickGet()
2 {
3 Canvas.SendEvent(new GetItemEvent());
4 ClearCompleteTime();
5 ShiftState(BuildBoxState.Start);
6 }
这里有一个问题是,为什么不在建造完成时就清理数据呢,因为有一种情况是,建造完成后,玩家还没来得及点击收取,就直接进入了离线状态,如果此时再次登录时数据已经清空,那他将做了一场无用功。

说不定直接垃圾游戏毁我青春败我前程了,为了避免这种情况发生,我们只有确保玩家真正收取到资源的那一刻才能清理数据。

到此,整个建造的基础逻辑已经梳理完毕。如果要实现快速建造的话,也只不过是将拟定的完成时间直接设置为此刻即可。如果之前记录的是开始建造的时刻,此时又会进行更多额外计算。

接下来,关于时间的坑这里也略提一二吧,一开始我以为记录时刻只需要记录时分秒即可,因为最多的建造时长也不超过10小时一般,游戏要保证玩家每天登陆,不可能动用海量的时间去建造一个资源。

如若如此,策划很可能会马上被抓出来祭天,并被玩家评论区冰冷的口水淹没。

但后来写着写着就发现了一个问题,那就是好多天没登录的玩家怎么办,只记录时分秒根本没办法判断时间的早晚,后来想一会还是把日期也记录下来吧。

1 public struct TimeData
2 {
3 public int DayOfYear;
4 public int Hour;
5 public int Minute;
6 public int Second;
7 }

要是你问,那一年以上没登录怎么办,那只能说,你建造的资源已经被时光的齿轮碾碎了(允悲...)。后来突然想起来如果是某一年的最后一天呢...emm,还是老实写全吧:

1 public struct TimeData
2 {
3 public int Year;
4 public int DayOfYear;
5 public int Hour;
6 public int Minute;
7 public int Second;
8
9 public TimeData(int year,int dayOfYear,int hour,int minute,int second)
10 {
11 Year = year;
12 DayOfYear = dayOfYear;
13 Hour = hour;
14 Minute = minute;
15 Second = second;
16 }
17 }

完整时间数据管理脚本:

 View Code
完整建造脚本:

 View Code
 View Code
这里用到的UI基础类可详见之前写过的随笔:

https://www.cnblogs.com/koshio0219/p/12808063.html

单例模式:

https://www.cnblogs.com/koshio0219/p/11203631.html

补充:

通用确认弹窗:

 View Code

效果:

原文地址https://www.cnblogs.com/koshio0219/p/12988884.html

相关文章
|
3月前
|
图形学 开发者 UED
Unity游戏开发必备技巧:深度解析事件系统运用之道,从生命周期回调到自定义事件,打造高效逻辑与流畅交互的全方位指南
【8月更文挑战第31天】在游戏开发中,事件系统是连接游戏逻辑与用户交互的关键。Unity提供了多种机制处理事件,如MonoBehaviour生命周期回调、事件系统组件及自定义事件。本文介绍如何有效利用这些机制,包括创建自定义事件和使用Unity内置事件系统提升游戏体验。通过合理安排代码执行时机,如在Awake、Start等方法中初始化组件,以及使用委托和事件处理复杂逻辑,可以使游戏更加高效且逻辑清晰。掌握这些技巧有助于开发者更好地应对游戏开发挑战。
138 0
|
4月前
|
图形学 C# 开发者
Unity粒子系统全解析:从基础设置到高级编程技巧,教你轻松玩转绚丽多彩的视觉特效,打造震撼游戏画面的终极指南
【8月更文挑战第31天】粒子系统是Unity引擎的强大功能,可创建动态视觉效果,如火焰、爆炸等。本文介绍如何在Unity中使用粒子系统,并提供示例代码。首先创建粒子系统,然后调整Emission、Shape、Color over Lifetime等模块参数,实现所需效果。此外,还可通过C#脚本实现更复杂的粒子效果,增强游戏视觉冲击力和沉浸感。
224 0
|
4月前
|
开发者 图形学 前端开发
绝招放送:彻底解锁Unity UI系统奥秘,五大步骤教你如何缔造令人惊叹的沉浸式游戏体验,从Canvas到动画,一步一个脚印走向大师级UI设计
【8月更文挑战第31天】随着游戏开发技术的进步,UI成为提升游戏体验的关键。本文探讨如何利用Unity的UI系统创建美观且功能丰富的界面,包括Canvas、UI元素及Event System的使用,并通过具体示例代码展示按钮点击事件及淡入淡出动画的实现过程,助力开发者打造沉浸式的游戏体验。
105 0
|
4月前
|
图形学
Unity动画☀️Unity动画系统Bug集合
Unity动画☀️Unity动画系统Bug集合
|
6月前
|
存储 JSON 关系型数据库
【unity实战】制作unity数据保存和加载系统——大型游戏存储的最优解
【unity实战】制作unity数据保存和加载系统——大型游戏存储的最优解
176 2
|
6月前
|
图形学
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统(下)
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统
89 0
|
6月前
|
图形学 容器
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统(上)
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统
90 0
|
6月前
|
图形学
【unity小技巧】Unity中实现一个战斗连击连招系统,可以动态添加减少连击连招段数功能
【unity小技巧】Unity中实现一个战斗连击连招系统,可以动态添加减少连击连招段数功能
127 0
|
6月前
|
存储 JSON 图形学
【unity实战】制作unity数据保存和加载系统——小型游戏存储的最优解
【unity实战】制作unity数据保存和加载系统——小型游戏存储的最优解
187 0
|
6月前
|
存储 图形学
【unity小技巧】unity事件系统创建通用的对象交互的功能
【unity小技巧】unity事件系统创建通用的对象交互的功能
61 0