前言
再不写开发日志,这个系列日志马上就会长蘑菇。
没想到一个月一眨眼就过去,这个月迟迟未写日志的原因,是陷入了制作联网功能的泥潭之中。在学习的过程中,不得不正视一些被我不断推迟的代码知识,这些知识阻碍了深入学习的可能。
本次则聊一聊让我陷入泥泞的技术方案,产生的原因以及过程的思考、感受等等。
并以此延伸一些我个人关于技术对赌的认知,顺道聊一聊一些额外的话题:关于技术散修方面的一些看法以及简要分析(胡说八道)。
满身污泥
SteamLobby
SteamLobby是Steam提供给开发者的一个联网大厅,每一个Steam应用的steam_appid提供了一个专门的房间。这有点类似浩方平台提供的房间号,能够让玩家聚在一起玩局域网游戏。(大概)
而Mirror能够让Unity快速搭建局域网游戏——让其中一名玩家成为主机端,而其他玩家则转变为客户端。
(读取steam用户,和简易的大厅设计)
Steam_appid:Steam应用的识别ID。
Mirror
Unity的一个局域网插件,能够让开发者快速制作出局域网功能游戏。
Mirror提供了一个快速进行局域网联机的框架,通过使用提供的组件和派生类,能够简易而快速地做出一个局域网联机游戏。
但是,能够方便快捷的前提,需要从一开始就按着他的路子来:
- Mirror提供了一个用来管理服务器的NetworkManager类,当玩家以客户端的身份加入游戏之中时,这个NetworkManager会生成一个与客户端对应的预制物。
- 而每一名玩家的输入输出都会与该预制物绑定。
这种设计与我的代码设计是冲突的,我此前是通过控制器驱动与预制物、玩家进行绑定,已经有了InputSystemManager珠玉在前,再来一个NetWorkManager,极有可能产生灾难。
(如果有能力拆分Mirror,这些便不是问题。)
除了上述一堆头痛的问题之外,还有一些让我喘不上气的问题:
- 重连如何处理?
- 网络适配如何优化?
- 控制器怎么交换?
- 如何才能够让联网数据松耦合?
- 会不会因此影响本地模式?
- 更高的fixedUpdate帧率,会不会产生变故?
- 大厅怎么设计?怎么清理无效用户?
- ……
当我把这一连串的问题打出来以后,甚至产生了不想继续的念头。
(但还是打算继续投入两周学习通信知识,看看能不能挽回沉没成本。)
当然,也不是全无收获:
- 比如在拆分Mirror的案例时,它对于特性的应用引起了我极大的兴趣。于是我现在正掉头重新学习反射与特性,也是为了将来可能用到的IOC做准备。
- 网络联机功能最好不要从开发中途加入,伤筋动骨。
- 以后只看流行的技术,生僻技术不看。
(插播一句,如果第一次开发联网游戏,可以用虚拟机测试。)
跌落泥潭
去年的开发计划里没有《抛投!》的联网功能,因为这会产生太多超出原计划边界的学习成本和制作成本。
另外,在技术选型期间,曾看过一些Photon的教程(能够让Unity网络联机的一个技术方案)。
- 但没有与之对应的,足够深入的教程。
- 担心掌控得不够深,会出现技术崩塌。
这两点让我很果断的抛弃了联网的想法。
但今年有朋友告诉我Steam提供了很便捷的联网功能,我顺着关键词看了看,竟然还有Steamwork的.net文档适配。(https://steamworks.github.io/)(当时没认真看)
在我的幻想中,调用几个API就能够搞定。于是顺手浏览了几个通过SteamLobby联网的教程,感觉可以尝试。加之老朋友们直言不讳:你不做联网,死路一条。
咬咬牙,决定投身网络模块。
紧接着,一头撞到了墙上:
- 不具备通信知识,导致对这个事情的风险评估严重失调。
- 以及,不清楚程序中间发生了什么。致使敲代码的过程,有一种失重感。
- 这个Steamwork的.net文档,实际上没有C#对应的API解释,需要参照官方的C++进行理解。
- 因为不懂C++,无法评估投入到C++语法的学习会产生多少风险。
- 简中缺少SteamLobby+Mirror足够深入的资料
- Mirror提供的exsample啃不动,文档有诸多对不上的地方。
------
技术选择与对赌
上面简单的分享了这一次失败的联网尝试,而这些经历让我再次思考着如何改良自己的学习路径。
独立游戏开发者一个很重要的品质,是在决策时注重风险与收益的比较。
技术学习的过程,实际上需要投入非常多的精力去评估每一次学习的成本与收益。因为市面上的可选技术线实在太多,各个技术线的拥趸者都在呐喊自家的技术线天下无敌。如果在动手之前不仔细思考,那么幸幸苦苦获取的知识最终很可能被遗弃在脑海的某个角落。
那么,关于技术线怎么选取?
每个开发者自身具备的经历都不可复制,而应对的需求场景又截然不同。想要使用某种万金油解决,必是不行。
所以很多时候,都是在风险与回报之间取舍。
这让我想到德州扑克——独立游戏开发的技术抉择,很多时候像是在打德州扑克。
- 手牌——个人的认知、技术优势。
- 公共牌池——市面上公开的技术池。通过学习公开技术,与自身的优势产生组合。
- 对手的牌——未来的坑。对手的牌如果能与公共池组成更强势的结果,那已经上了牌桌的其他开发者就会无路可退。
- 筹码——开发者的时间与资金。
如果把独立游戏开发这件事剥离成商业行为,那么大概就是这么一回事。
说个题外话,独立游戏开发的诈唬对应什么行为?
我认为是还未度过愚昧之峰的开发者们,疯狂渲染某些技术的难度。
把德州扑克的对赌思路映射到我的本次经历
- 现存的代码知识就是我的手牌,而联网功能就是还未掀开的公共牌。
- 当我自信满满地打开下一张公共牌,与手牌一合计发现不达理想,最终叫苦不迭。
这种信息不对称本是常态,如果没有一个优秀的先行者带路,那么在这个信息嘈杂的赛博垃圾场四处碰壁才是日常。
本次的一些反思:
- 将来学习自身空白领域时,如果技术对应的流通度不够高,不会考虑。
- 除非有值得这么做的高风险高回报。
- 什么时候最合适技术冒进主义路线?首先得自身专精这个技术线,此外还有大量的空余时间。
- 独立游戏开发的过程,很多时候学习的有效时间是无法挤出来的,大部分工作都是在消化曾经堆积的知识。
- 当坚定要学习已经流通于市面的知识时,学会实际是必然的,真正困难的点是如何提高学习效率。
散人之道
散人之道,即是指开发者需要让自己成为多面手。
所谓散修,即是指学习者不专精某个方向的技能。最终演变为通才,是为散人。
这里尝试简要的分析散人的特点与利弊。
首先说说散人的特质:
- 散人需要在记忆与遗忘之间找平衡。
- 散人各不相同,最好独具一格。
记忆与遗忘的平衡:
- 如果开发者的遗忘能力太弱,难以忘记东西。那么脑海里无数的想法会不断干扰工作,导致效率下降。
- 如果记忆力过低,那么学习的知识容易变为过往烟云。每一次重拾旧的知识,将会浪费大量时间。
- 无奈的是,遗忘与记忆是一个对立的属性,散修需要在二者之间找到平衡。
- 人的大脑容量以及思考检索是有限的,在此前提之下,越简单有效的方式,能包罗的内容越广。
虽然记忆与遗忘,是人的天然。但若专精一路,能够选择的解决方法自然就多一些。
专精路线有大量时间研磨技术,甚至技术线粘度极高,无形中在反复记忆,如此对于记忆与遗忘的宽容度就会很高。
但散人则不是那么容易——散修需要面对的知识量过于庞大,路线极易走歪。
散修的劣势
先提劣势,摆正姿态。
- 散修不能专精某一条技术线。
- 一个打螺丝的你,和一个散修的你。散修的你会比打螺丝的你更专精吗?
- 散人难以甚至无法回到之前专精职位的高度。
- 一来,人的记忆会衰减。
- 二来,游戏技术具有时效性。怎么保证自己能稳固特定知识,且保证社会不会进步?
- 不经意之间的鄙视链底层。
- 已经散了,就放下社会达尔文意识吧。
- 每一次前置知识的启动,所耗费的时间与精力。
- 人会遗忘,散人需要时刻与遗忘进行对抗。要么需要大量投入复习时间,要么每一次都要打开文档或者教程重新回忆,要么整理成能够快速使用得工具。
- 时间不够用。
- 回头是岸
优势
- 大部分时候能让项目落地,可能性最高的是身为程序员的制作人。但实际上散人才是。
- 能够与对应职位的工作人员共情
- 设计工作流的可能性更高
- 对实用性更敏感
- 低姿态
----
关于写日志的一些新理解
之前写的日志,现在再回顾就能够发现问题。原因大概是因为写的时候,脑海里的热认知能够自动脑补内容。而现在认知冷却了,随即能够发现有些事情描述得太抽象,又或者是内容转进太快。
而写日志这件事情从最开始的紧绷,到随性,到现在慢慢摸清楚该怎么风格化:
- 不可以太紧绷,不可以太随性。
- 不能够混沌,不能够无用。
- 不要正经,不要无趣。
- 不扣细节,不丢逻辑。
尾声
最近精神状态又开始紧绷了,一个原因是制作联网功能时,心里上产生的不确定性。另一个是《抛投!》的占地玩法的核心,我认为有严重的缺陷,但又没法设计出有效的视觉表达方式。除非将这个玩法彻底抛弃,但这么做的话就完全背离设计起点。
这同时也是一个有趣的事,因为在最初设计这个游戏时就已经出现了伏笔。
在立项之初,我思考和分析过几个流行的微信游戏,他们大部分都被设计成了快速反馈的机制。而我最初在脑海里构建《抛投!》的弹刀、压刀、占地机制时,把他们定位成了快速反馈的机制。
但在实际设计中,我害怕玩家的负反馈太强烈,以及策略深度不够,于是让武器落地变成了一个时间队列的方式——根据武器先后落地决定他们的权重,先出手的武器被破坏后,下一个武器的权重上升。
在思考这个设计的时候,浑然不知这个微小的设计即将带来的灾难:为了填一个坑,又营造了无数个坑。
(通过文字与语言,很难描述清楚这个占地相关的机制,未来会特地拆分出这个失败的设计。)
这让我有了一个猜想:如果一个机制的表达无法在三步之内画上句号,那么就是个失败的设计。
未来我会尝试验证这个猜想。
-----
如果能给我的日志风格提建议,那就最棒了。
作为一个散修党表示认同,自从接触了其他领域上的技能后发现宽容度高了不少,对于一些水平不如自己的,从之前会想这个人怎么这么菜,变成了这个人只是暂时水平有限而已,没准之后比我厉害。我想可能是因为在学习其他领域上被人吊打的经历使得自己有了一点宽容心哈哈。
PS:对于写日志的风格我觉得写得开心就好,如果非要提建议的话,我认为写日志前先想好读者能够从中获得什么。以这篇日志看,在我看来这篇日志的目的是分享观点,读完后我个人感觉关注点有点分散。例如一开始是关于联网从入门到放弃的过程,然后借此表达技术对赌的观点。有实例的观点是非常好的,但是实例最好不要太过繁杂,如描述联网那部分有挺多的技术细节,在我看来其实也没必要一一细说,重点是要表达因为不熟悉而导致联网实现中遇坑,为的是后面的观点做示例,联网遇坑的过程我觉得其实两三句说明就好。
@mnikn:
非常棒的建议,包括上次建议我把Gif整合成一张图片。
1.关于思索读者角度这个事,我感觉自己想得太复杂了。我意图通过日志来锚定自己的轮廓,以及开发过程的轮廓。这是为了未来的队友而考虑的,他们能够从我的这些发散之中看到我的轮廓。比如未来某天一个路人,看到我对某个冷门游戏主题的耕耘,他们可能会产生了解的兴趣,而这些日志就会成为注脚。(当然,可能我的思路不正确,导致适得其反。)
2.关于阅读关注点分散这个事,之前@π也提到过这个问题,这确实存在而且很严重。以超链+专题的方式实际上对读者会更友善,但专题的内容需要大量时间深耕,这会阻碍开发思路和进程。如果把技术的细则剥离,只留下经历与感受,又会导致“围绕项目”的关联度大幅度下降。
3.我现在还在想办法设计出一种能够勾勒轮廓但又不分散的写法,但暂时还未找到解决之道。这次我迟了一个月写总结,也是因为意识到自己写的开发日志太散。如果实在不行,就只能分离内容了。
4.之前也试着压缩过技术细则的分享,但总感觉不安。压缩很有必要,但还在摸索。
建议:
“通过文字与语言,很难描述清楚这个占地相关的机制”,往往文章里出现这种表述的时候,就是需要图像或Gif的时候。除非这不是本文分享重点。
文中涉及只有自己或少数人熟悉的事物、技术时,需要考虑没接触过的读者能否读懂这段在说什么,由此,哪怕多写一两句解说,显得啰嗦,也不为过。
@ThirtyThree:
OK,下次会注意。这个机制是因为设计得有些复杂,外加偷懒没录屏。
最近我也在学习多人游戏的开发,深感这件事情并不是“找个文档学习两下”就可以加入游戏当中的。多人游戏必须一早就开始规划。其 API,架构设计都会受到很重的影响。
加上我正在参与一个跨平台 UE5 项目,到时候也打算写一篇入门文章记录一下这个摸索过程。
@Dluck:
真的是被折腾得不轻。
散修党+1
深感你所说的这些劣势。每次想要重拾以前的技能时,就会因为相隔久远的时间成本而停滞不前。当确实需要这些知识时,又会因为后悔未能早拾技能而感到无比沉重的压力。随后,当知晓时间对于学习技能的重要性后,这份压力愈发强烈,甚至于影响自己对新技能的学习。
看到你的文章后实在感同身受,想发发个人的牢骚,先说句抱歉……早几年未精进美术后,架上绘画功夫丢了,就很难跟上现在的数码插画趋势,自然也没法很快去适应游戏美术的内容;没有在小时候乐理知识最充沛的时候学感兴趣的编曲,现在想要制作些游戏配乐就非常困难了;正因为连重拾过往技能都如此困难,于是给了自己很多无谓的压力,如此,筹备学习代码这事更是望洋兴叹。也许确实如你所说——回头是岸,才是克服这些困难的正确选择吧?
@CoryluS:
欢迎讨论,本来写日志也是想看看能否从碰撞里产生一些新的认知。
如果身处的环境允许专精,那最好还是专精。在垂直领域深耕,人的精神状态会更好。散修的那种海量的不确定性,太折磨人。
@RockTaoist:
确实如此。总之借你建议,再努力努力了!