【开发者日志-硬核版】来吧,让我们来点程序员之间的对话!

修改于10/28168 浏览综合
程序员的3D打印机很想工作一下
参与方式:关注游戏 + 关注发帖账号 + 回复活动帖
结束时间:2024-11-08 20:00:00 自动开奖
🌟游戏可以下载试玩啦!戳:https://www.taptap.cn/app/726167🌟
🌟我们有玩家群啦!欢迎加入🌟
🌟QQ群号:787650303🌟
【免责声明:本文由我们的开发大佬生成,由于本人实在看不懂,所以干脆放弃翻译,懂的人自然会懂!】
【感恩回馈,本篇抽10位小伙伴送3D打印的开关小玩具!】
TapTap
开关长这样,但会改成我们的限定配色!敬请期待!
horizontal linehorizontal line
在项目的开发中,除了传统程序员会负责的功能实现,我更主要的关注点是:
- 项目的整个整体3C,Gamplay的合理实现
- 代码可读性
- 项目时间管理与风险控制
- 不同工种之间的整体工作流

1. 项目的整个整体3C,Gamplay的合理实现

这是传统意义上的开发内容,通常都非常琐碎。例如实现基于Character Controller的角色移动,基于Cinemachine的摄像机控制以及基于Unity New Input System的控制器。
其中比较有趣的是,由于我们需要能够在玩家按住R2/向后滑动鼠标滚轮时拉远摄像机,给玩家提供一个更好的全局视角,帮助玩家理解地图,我使用了一个叫【Mixing Camera】的组件,并通过调整跟随玩家摄像机和全局预览摄像机的weight,实现了顺滑过渡。
TapTap
效果示意
根据策划案的需求,在玩家移动时,应该将摄像机过渡至跟随玩家摄像机——原本我应该将摄像机的默认参数设置为跟随玩家摄像机,这样玩家启动时就可以直接移动,但是由于我忘记了调整Mixing Camera中的默认weight[表情_惊恐],导致每个场景启动的时候,都会触发从全局预览摄像机的过渡动画。
理论上这是一个小bug,但是在看到效果后我觉得非常有趣,给游戏的启动提供了一些动感,因此我将其作为功能保留了下来。
在Gameplay上,我们需要能够支持单个开关支持多个灯、窗、门的开启关闭,同时,一个灯、窗、门也可以被多个开关控制。因为这里使用了非常经典的OOP(Object-Oriented Programming),将所有开关抽象为Generic Switch,将所有的灯、窗、门抽象为Generic Receiver。
TapTap
灯具动画集合
Switch检测了玩家的位置和行为,如果玩家靠经并通过了条件检测,那么高亮自身,如果此时玩家点击交互按钮,那么它会向自己所管理的Receivers发送消息。至于Receiver会干什么,它不知道也不在乎。
而Receivers接到消息后,会触发各自的行为,根据配置的不同,会播放声音,播放动画,启动或者关闭组件,等等。同样,它不在乎是谁发了消息。
在Gameplay的实现上,我对于Singleton的使用非常敏感,我要求尽可能地少用Singleton,各种系统尽量通过成员地方式存在某个现有的类上,而不是通过Singleton的方式创造一个新的管理器。如果一个东西真的有必要被调用,那么它应该存放在一个我们称之为World Model的MonoBehavior Singleton中。
TapTap
我认为,滥用Singleton无异于破坏OOP的逻辑,它会导致各种Manager,System的泛滥。
首先,由于Singleton依赖于Class的全局性质,实际上调用Singleton的方法与将函数放置在全局作用域无异。
其次,由于Singleton的存在,破坏了原本调用顺序,导致需要一系列对于Initialization和Uninitialization的精细控制,一旦不小心以错误的顺序unload singleton,就会导致大量的错误,并且需要防止出现Reference Circle。
最后,从语义上来说,一个Singleton Maneger会导致代码失去原本的层次结构。
例如,一个管理玩家在游戏中收集到的证言的系统,是否应该放在Singleton中?我的回答是不,既然只有玩家会访问到这个系统,同时,NPC不会拥有证言系统,那么没有任何理由让它成为一个Singleton,一个漂浮在游戏整体系统中的幽灵,甚至在游戏启动时它就可能存在。
我认为,应该尽可能地遵守Composite Pattern,在确实有必要的时候大胆使用Singleton。绝对不应该的事情是为了不去阅读代码,只是从方便自己的功能实现的角度,就贸然引入Singleton。

2. 代码可读性

代码可读性对于一个项目来说非常重要,通过简单的几条规则,可以大幅优化可读性。
- 不要使用缩写。
- 不要过度设计。
- 尽可能让名字符合它的实际功能,如果不符合,尽快修改。
- 删除不需要的代码
- 认真地处理换行
- 正确掌握关键字的语义
这里我只提一个,就是不要过度设计。我们在学生阶段都受到了培训,例如设计银行的管理系统,要求我们尽可能地使用抽象和接口,来实现一个优雅[表情_酷]的系统。
但是现实生活中,优雅的系统并不一定是可读性好的系统,在开始任何Gameplay框架的时候,请告诉自己,代码是要给别人看的,一个多层抽象的系统,意味着读者需要一层一层跳入最后的interface和abstract class去了解你的结构,如果不是复杂的项目,一个抽象结构可能只有一个具体的实现,那么这个抽象结构就是完全没必要的。
如果你很想设计,那么配备具体的文档和注释,帮助读者和未来的自己理解这个系统。
如果你不愿意写大量的注释,那么就从一开始就保持项目的简单,只在需要的时候去拓展它[表情_送花]

3. 项目时间管理与风险控制

时间管理是Game Jam最常见的问题,作为程序员,比起游戏有多好玩,我更在乎玩家能不能打开游戏,顺利地结束游戏。这是程序员的责任,去确保项目平稳落地。为了能够落地,我们需要在一开始就规划好时间[表情_看我的]
在这里,我们使用了【Google Calendar】去规划了一个大概的时间:
第一周,Kick Off Phase,需要验证玩法的技术可信性,搭建项目,设计初步框架,一些简单的关卡验证。
第二周,Alpha Phase,需要在alpha的结束的时候实现从头到尾的可游玩,尽可能实现功能。
第三周,Beta Phase,停止新功能开发,改bug,优化,打磨,并进行打包和QC。
一定要坚持在每个阶段结束每个阶段的任务,否则到最后就会乱作一团。
TapTap
工作日历

4. 不同工种之间的整体工作流

不同工种之间应该如何协作是任何团队要面临的问题,作为程序员,有义务为其他成员提供必要的IT协助,工作流定义。
抛开Git,SVN,Perforce这类协同软件不谈,更多的是需要处理Unity Scene的conflict问题,在这方面,我们采用了比较简单的Prefab方式,也就是把每个场景再拆成颗粒度更小的Prefab,例如Level Design和Level Art拥有各自的Prefab,在提交时,只需要提交对应关卡的对应工种Prefab即可,这可以减少conflict的产生,优化协同效率。
horizontal linehorizontal line
综上所述,项目开发不仅仅是功能的实现,更是一个团队协作、技术实现、时间管理风险控制等多方面综合考量的过程。通过专注于这些方面,可以更好地推动项目的顺利进行和成功交付。
TapTap
路透一个今天刚实装的关卡鸟瞰
[表情_送花]今晚我们将内部打包第一关的测试,试玩版很快就会和大家见面啦~敬请期待!
15
3
11