复刻之路-第一周、第二周
〇. 初始游戏计划1. 人员安排2. 内容安排3. 计划安排初期:中期:一. 开发进度1. 第一周- 学习背包系统和成就系统原理- 画万能Sprite2. 第二周- 开始着手制作背包系统3. 第三周- 截取“地球末日生存”的物品图片- 继续拓展和改进背包系统- 制作场景切换万用脚本4. 第四周- 着手制作 Minimap 系统5. 第五周- 搭建世界地图场景- 简单地制作一下UI- 实现玩家点击移动到目的地6. 第六周- 制作玩家输入系统- 运用 Navmesh 简单实现玩家移动- 制作玩家与周围环境互动- 制作地图生成器- 切换场景 BUG 修复- 游戏背景音乐和音效的引入- 数据持久化储存- 日志调试- 剩下的时间,做和箱子互动部分7. “留白”二. 反思和总结关于学习新知识:关于回顾旧知识:三. 未来规划〇. 初始游戏计划
1. 人员安排
本人:
主要负责游戏框架和玩法的实现(编程),其他的编程内容穿插其中,关于美术素材和数值策划的就在其他空余时间做做,音乐素材等到放寒假再做,其他的UI界面设计、Editor自定义编译器就先学习学习。
其他成员:
(暂时没有相关信息)
2. 内容安排
本次考核我将继续使用上一次考核开发的内容(CreateGame),把这个小项目通过改造和完善变成 “地球末日生存”。具体功能会有合成系统(耗费材料制作高级物品)、搭建系统(可以建造小屋和其他家具用具等等)、完善的背包系统(背包和其他界面互动,比如快捷栏界面、合成界面、任务界面等等)、成就系统等等。非常非常敬佩 “地球末日生存” 这款游戏!
关于游戏主体:
把上一次做的考核内容完善,把人物的模型和移动弄好,添加更多的物品,并且添加物品合成系统,再弄一个建造系统,顺便学习学习其中要用到的框架和逻辑。
关于游戏互动:
捣鼓敌人的AI系统,做出完整的怪物行为流程。然后在学习学习基础玩家输入和反馈的框架和机制,能够做到给玩家带来更良好的游戏体验。然后把完整的UI页面布局弄好。
关于开发工具:
开发出一套更流畅使用的UI开发工具(打算充分利用Unity的检视面板制作工具),能够达到下次开发还可以接着使用这些工具而非重新写一个。再构建一些多种场合都可以用的小工具(如果有足够的时间我就试着做玻璃碎裂那种的特效,还有屏幕适屏的改进等等,顺便学习怎么写 Shader(为了能够在 UI 上写出高斯模糊效果和 alpha 影响的 Mask))。
其余:
大部分时间会花在捣鼓怎么写良好的框架,不仅能够做到拓展性很好,还能在性能上有所帮助。
3. 计划安排
初期:
12月6号之前:
部分改善了一些管理类脚本,并用ShaderGraph做一些基础材质(史莱姆粘液等等)
从12月6号开始:
第一周:
学习和了解需要用到的各种系统的原理,并尝试做出成就管理系统和成就触发事件,并在此过程中修复之前留下的下部分BUG,统一改善代码的排布,使代码更利于后期开发,将代码写成安全性更高且拓展性更好的。
基础角色建模的构想和骨骼动画绑定,顺便画一些UI的万能Sprite。第二周:
着手搭建合成系统的框架和快捷栏系统。并做到此类UI的屏幕适配问题,顺便解决其他UI的屏幕适配和屏幕适配追踪。
对角色基础动作进行流畅的连接,并实现角色近战攻击判定和攻击特效,实现角色远程攻击的正向充足反馈和基础特效。编写武器的属性脚本,武器相关类和继承类,并时时刻刻保持高拓展性和高安全性的代码。第三周及以后……(暂未定······不过会按照内容安排推进)
(如果有期末周我会适当减小编程时间,但是建模和场景搭建的时间加长(因为我编程有成片的时间才能编程高效))。
中期:
从12月6号开始:
第四周:
由于是考试周,不做多余安排,修理修理小BUG,继续画一些Sprite。第五周:
把游戏中的全球地图视野完成,并完成玩家输入系统的编写,寻找合适的美术素材,并开始布置场景。
在全球地图视野中,实现鼠标拖拽和WASD两种方式的移动,并且将移动的过程平滑化,在移动开始加速快,移动结束后会继续按照惯性向前并逐渐停下。实现人物在地图上移动,点击目的地能够显示目的地消息。按照游戏中的UI布置摆放UI,并提前将未完成的部分添加“敬请期待”触发按钮。
制作每个场景,和世界地图;并实现摄像机第三视角跟随和世界地图的摄像机移动功能。
制作完如果还有时间就捣鼓捣鼓Minimap
的生成(玩家在Minimap
显示,箱子和建筑在Minimap
的显示等等)(注意:不能直接使用Render Texture
因为这个会较大程度上进行没必要的性能损耗,并且这样的小地图不美观(即使使用Layer
去除和挑选,消耗的性能也没有UI生成Minimap
好 ))。第六周及以后……(暂未定······不过会按照内容安排推进)
完成各个地点生成资源的脚本,玩家在地点的移动脚本,和与资源互动以及反馈的脚本。
基于考核前所给的资料,进行系统性的学习,将代码结构优化,代码命名规范,代码内部逻辑和分工独立,把整体代码优化一遍。
实现玩家和箱子,工作台等的互动,并且在互动时激活数据读取,在关闭界面实现数据储存(或者离开场景或OnApplicationExit
时储存数据)。
完善UI界面的布局,达到和 “地球末日生存” 类似的效果,尽量复原其所有操作。
(时间非常充裕,这次好好学习关于数据持久化的知识)
(如果寒假开始了就多花点时间在脚本拓展性和安全性的研究上,减小耦合度,增加聚合度)。
一. 开发进度
1. 第一周
由于这周是考试周,所以没有太多成片时间来编写框架,于是就把碎片时间花在学习背包系统和成就系统原理上。而且画一些万用的 Sprite 也是利用碎片化时间很好的方式。
- 学习背包系统和成就系统原理
各系统构思:基于面向对象编程模式:
创建型设计模式:侧重于对象的创建。结构型设计模式:侧重于接口的设计和系统的结构。行为型设计模式:侧重于类或对象的行为。
背包系统的组成部分可以分为:
物品本体
:储存物品数据信息。
物品容器
:负责发出对物体本体进行移动、传递、接受等请求,并实行。
背包管理者
:负责接受物体容器发出的请求指令,并给予回复。
其他
:(这里不显示详细信息)。
可能存在有不正确的地方,请大家多多指教
基于C#委托和事件:
成就系统的组成部分可以分为:
成就信息载体
:负责储存成就(触发条件和完成的反馈),和完成后对应的奖励。
成就信息发布者
:储存成就信息载体,并游戏开始时,一一发送成就信息载体所储存的成就信息。
成就奖励发布者
:当成就信息载体储存的成就触发后,将奖励信息发送给成就奖励发布者,一定条件触发(关闭背包界面或打开成就界面)(或没有触发条件)时给予玩家奖励。
其他
:(这里不显示详细信息)。
注意:这里只是博客主个人一开始的思路,并不代表一定是对的,但是后期会慢慢完善。
- 画万能Sprite
画一些简单的在 UI 布局中经常用到的 Sprite,还有按钮图案等等。
上图:地图标志点的图标其他图都是纯白的,这里看不了,就不放上来了
2. 第二周
- 开始着手制作背包系统
由于上一次考核做的背包系统是空间占有型背包,拓展性较差,而且不适用于 “地球末日生存” 的复刻。所以本人重新做了一个背包系统,并且在拓展性上留了心眼。
本人认为的背包系统的基础框架如下:
详细信息见:
1.Unity 简易背包系统:简单的拖动,储存和回退;
2.Unity 简易背包系统:物品展示框;
3.Unity 简易背包系统:工作台合成和配方;
4.Unity 简易背包系统:可数物品,数值化储存;
后面的时间在完善和改进背包系统的框架。
由于考试周还没结束(紧张又刺激),所以就也只做了一点点。
3. 第三周
- 截取“地球末日生存”的物品图片
截取 “地球末日生存” 道具图片,经过PS处理,使用在拖动单元上。截取了如下几个物体:
- 继续拓展和改进背包系统
继续为背包系统做拓展和可拓展性检查,并开始着手制作场景切换万用工具和Unity编辑器工具:
本人在背包系统完善了:
可数型单元工作台及燃料消耗单元,还有过程展示条。
单元信息展示框(并实现了不管文本内容多丰富,内容显示框都会随着内容量适配)
单元垃圾箱(主要功能是删除物品,如果想要回物品,可以随时取出)(后面还会制作出垃圾箱最大容量)
单元锁(直接和拖动单元融合,避免不必要的性能损耗,在拓展性上也做了相对应的保障)
单元拖动时动画更加流畅,以及按钮触发更加像 “地球末日生存”
- 制作场景切换万用脚本
制作思路:
切换场景UI布局可以由游戏提示,加载条和背景面板组成,整个Canvas
通过场景切换管理者脚本实现DontDestroyOnLoad
,从而可以在每个场景自由切换。(其他的可能引起的按钮失灵等问题后面解决)
脚本由场景切换管理者通过把碎部任务发送给游戏提示管理脚本,加载条管理脚本和背景面板管理脚本组成,其中它们分工情况如下:
游戏提示管理脚本
:负责管理提示的图片,标题和文本。(还有每次切换场景都随机抽取一条游戏提示显示)加载条管理脚本
:负责储存进度的数值和显示进度加载情况。背景面板管理脚本
:负责在场景切换时,控制背景的显示隐藏或者各种切换场景时的行为动画。场景切换管理者
:控制场景切换,管理以上所有脚本。
更多的内容如下:(这仅仅只是一小部分)
接下来附上管理者场景切换管理者的场景切换迭代器:
主要是看备注思路,里面的内容按情况更改,可以根据不同游戏需求更改
public void LoadScene(int index){// 初始化(进度条清零,资料卡随机)m_InfoSettins.SetInfo(m_GameGuide);m_LoadTool.Init();// 显示加载界面StartCoroutine(FakeLoadScene()); // 显示假的进度条,因为前期进度条在准备,先假装在加载m_MainPanel.Appear(1, () =>{// 场景加载StartCoroutine(StartLoadScene(index));});}private IEnumerator StartLoadScene(int index){// 1. 开始加载场景,并禁止加载完立即跳场景AsyncOperation asyncOp = SceneManager.LoadSceneAsync(index);asyncOp.allowSceneActivation = false;// 2. 加载场景以及显示加载过程float curProgress = asyncOp.progress;do{m_LoadTool.Load((asyncOp.progress - curProgress) * m_TrueProgressRate);curProgress = asyncOp.progress;Debug.Log(curProgress);yield return null;} while (asyncOp.progress < 0.9f);// 3. 载入场景asyncOp.allowSceneActivation = true;// 4. 将最后的 "10%" 跳掉while (!asyncOp.isDone)yield return null;// 5. 做剩下加载场景完要做的事情pleted += (asyncOp) =>{m_MainPanel.Fade(1);ScreenScaler.Fit();};// 6. 然后再把进度条 lerp 到终点while (!Mathf.Approximately(curProgress, 1)){float tmpProgress = Mathf.Lerp(curProgress, 1, 0.5f);m_LoadTool.Load(tmpProgress - curProgress);curProgress = tmpProgress;Debug.Log(curProgress);yield return null;}}
4. 第四周
- 着手制作 Minimap 系统
制作思路:
如果缩小迷你地图的使用范围,最常见的还是直接在 UI 上面显示迷你地图;如果要扩大一点它的使用范围,可以是玩家在第三人称下手中拿着的地图,也可以是全息投影,任意旋转(包括人物非法线方向旋转)的迷你地图。而我这次就把范围缩小到只在 UI 上面显示,以防后面的时间不够用。
脚本由迷你地图面板通过传递逐帧更新显示迷你地图元素实时对应的位置的方法给迷你地图更新者,下面是更详细的情况:
迷你地图元素
:负责显示场景元素在迷你地图的位置(或和旋转或和比例),并持有更新元素状态的方法。(其实就是一个图标,带上一个能够被迷你地图面板识别的组件)迷你地图面板
:负责储存迷你地图元素,并持有添加和删除迷你地图元素的方法,并在初始化时辨识所有迷你地图元素。迷你地图更新者
:持有迷你地图面板,并实时更新迷你地图面板中的各个迷你地图元素。
为什么不用 RenderTexture 来制作迷你地图呢?
答: 用 RenderTexture 制作迷你地图也可以,不过用上面的方法制作的迷你地图可以有更好的拓展性和更优的性能。用 RenderTexture 制作迷你地图确实可以更加灵活,不过是以性能为代价换取的,至于怎么影响性能(多一个相机渲染,还是有深度的那种渲染,并输出在 RenderTexture 里面,性能肯定会比直接等比映射差),这里不做过多的解释。
演示视频如下(注意迷你地图图标和实地图标位置的变化,还有玩家旋转,并处于地图中心),实现传统的迷你地图系统:
5. 第五周
- 搭建世界地图场景
在AssetStore中寻找素材,素材如下:
并简单地摆放场景:(几乎都是按照游戏原内容还原的)
家(Home)一级林(PineHurst)二级林(PineGrove)三级林(PineForest)一级岩(LimeStoneRidges)二级岩(LimeStoneCliffs)三级岩(LimeStoneMinarets)
- 简单地制作一下UI
其中有用到 PanelStack 以顺序管理界面的弹出和回收。下面是简单的框架内容:
还有做玩家收集物品后的消息弹窗。下面是框架内容:
- 实现玩家点击移动到目的地
由于能量消耗实现原理很简单,所以在演示前没有写能量消耗相关代码。
到此世界地图部分就告一段落。
6. 第六周
这一周内容太多,一时间不知道从何说起,就先列这些点,后面慢慢补。。
- 制作玩家输入系统
- 运用 Navmesh 简单实现玩家移动
- 制作玩家与周围环境互动
- 制作地图生成器
- 切换场景 BUG 修复
- 游戏背景音乐和音效的引入
- 数据持久化储存
- 日志调试
- 剩下的时间,做和箱子互动部分
7. “留白”
计划总是赶不上变化,很多实际行动都没有和计划一样,因为每天计划的小点都在变。做了背包系统,就想把它做得以后能够一直用到(拓展性非常好的那种),然后就把时间都投入进去了。
对于场景切换部分,由于场景切换可以通过DontDestroyOnLoad
实现场景间的交流,我就一直卡在如何用DontDestroyOnLoad
实现各种功能,导致花在上面的时间太多。
而后的成就系统就先搁置在那了,因为成就系统和任务系统不说是非常像,思路简直一模一样,而 “地球末日生存” 后来才推出任务的,所以我就在这个时期先不把成就系统做出来了,先尝试做 “地球末日生存” 初期的样子。
二. 反思和总结
关于学习新知识:
这次制作背包系统,让我学习到了如何更合理地运用泛型,继承和接口,并使用接口及其拓展方法实现了类似多继承的效果,在也学到了很多关于更好运用泛型的知识(比如IComparable
接口与泛型配合使用的效果超群,拓展方法里this T t
的妙用等等)。这也为我未来计划做Tween
包做铺垫(this.set().set()
之类的妙用,比如在调试上DoDebuger.Log()?.Send("发送消息");
如果已经Build
了,可以把DoDebug.debug = false
,然后DoDebuger.Log()
放回值为null
,就省去了创建字符串的性能消耗)。
如下:
using UnityEngine;public static class DebugHelper{#if UNITY_EDITORpublic static bool enableDebug = true;#elsepublic static bool enableDebug = false;#endifpublic class Message{public static Message Nothing = new Message();public Message() {}public void Send(string message){Debug.Log(message);}}public static Message Log(){if (DebugHelper.enableDebug)return Message.Nothing;elsereturn null;}}
使用的时候就直接:
DebugHelper.Log()?.Send("测试中...");
当然上面也是我比较浅显的理解。
这次学习我不仅在脚本编写上学到了很多,而且在UI布局上也是到如何合理地用Anchors
和Pivot
。
关于特性的学习,终于找到了可以通过脚本获取方法的知识了,GetType().Method
又是个值得学习的部分,适合用在自定义编辑器部分,到时候可以自己写一个拓展性更高的UnityEventLike
。
(其他的也回忆不起来了)
关于回顾旧知识:
对UnityEvent
和C#委托事件的使用更加熟练,在百般尝试之后,能够分清什么时候要用委托事件,什么时候更适合用UnityEvent
。
管理者框架确实非常非常好用,对性能也非常友好。
学习了新的框架,使脚本通过玩家输入来实现游戏里的基本操控,能够在后面脚本管理和拓展性有良好成效。
实现了和 “地球末日生存” 里箱子互动差不多的功能,比较好地解决了储存的数据持久化问题。动态加载数据等等的功能。
三. 未来规划
为了CUSGA
上能够获得好名次! 冲刺!
如果觉得《游戏开发之路之“复刻或升级游戏”---地球末日生存》对你有帮助,请点赞、收藏,并留下你的观点哦!