游戏开发中的原则性问题总结(持续更新)

游戏行业是程序员最理想的行业
我入行时间不长,工做之中也没什么人指点,老是犯下许多错误。有的错误是行业经验欠缺致使的,属于结构性错误;有的则是代码规模经验缺失致使的,属于原则性错误。这两种错误互为因果,我把一些原则性的问题记录下来,既检讨了本身也愉悦了他人。前端

游戏开发问题篇

术语不统一问题:

  • 这个问题每每是策划不够专业致使的。策划作的文案,经常带有很强的主观臆想,用一些“情景式”、“过程式”的方法描述一个概念。
  • 好比在作副本系统的时候,策划给的术语“每一大章的每一小关里面分前置关、普通关、精英关三种关卡”,这里面的不少概念都没有成文的叫法,无法对应到你们熟悉的英文,致使配表、协议中出现各类版本的术语。前端的同窗干脆用汉语拼音了事,实在有违各类开发规范。。
  • 方案,必须在配表、定协议以前先统一术语,把各类须要复杂描述的概念统一块儿来,对应成一个简单的单词。好比,“第一章”里面的,叫chapter。“第一节”里的,叫section前置关town普通关country精英关city。这些单词有些是杜撰出来的含义,可是可识别度很高,容易记忆不会形成歧义,就足够了。编程毕竟是要写英文字母的工做,汉语里的概念对应到英文的时候至关于一个抽象翻译过程,在团队协做的时候先把英文术语统一块儿来能够减小不少沟通成本

数组最大长度问题:

  • 不少结构体的最后都是一个不定长的数组,在代码中是用最大长度表示的,实际上用不到这么大,咱们须要一种真正精简的方案。
  • 譬如,stItem _items[MAX_ITEM_NUMBER];若是MAX_ITEM_NUMBER等于100,运行时这个对象就占100*sizeof(stItem)的空间,而实际运行中可能常常在50左右,浪费了不少内存,还可能致使没必要要的copy。
  • 方案,使用柔性数组做为容器,可是相应的必须有一个配套的内存池,才能保证不频繁的申请释放内存。上例改为stItem[0];就能够任意扩展stItem的个数,不受MAX_ITEM_NUMBER限制,也没必要占用MAX_ITEM_NUMBER个元素空间。注意不能直接在栈空间使用柔性数组,会把函数调用栈破坏。

集合大文件问题:

  • 像配表读取、协议处理、结构体定义等的代码每每天生容易扎堆到某个文件中,使其膨胀巨大化。
  • 文件巨大的惟一好处就是容易定位文件,但缺点是不容易定位目标代码,改动频繁,每次改动都要从新编译次文件,生成目标文件过大。若是是头文件巨大化,就会致使频繁的编译。
  • 因而当咱们的集合文件超过了其应有的清晰整洁度以后,就要走向“合久必分”的不归路。在拆分集合文件的时候我发现最好是有个索引文件把全部分散文件的关键参数聚合起来,方便统一处理。这时候我基本是靠宏定义,尽管用一个宏函数把我关心的参数包起来,等须要统一处理的时候定义这个宏的真实意义就行了。

手工序列化问题:

  • 通讯协议采用的是二进制数据块的形式,收发消息也就是结构体序列化问题。若是用手工序列化,无疑会致使不少枯燥无味又极易出错的工做量。
  • 方案,客户端使用unity,借助C#的反射机制能够实现自动序列化,只要保证client和server的结构体一致便可。C++部分因为大部分序列化操做都是直接memcpy对象,问题不大,就没有作。按理应该用模板技术作一套自动序列化和反序列化的工具,若是有实现的同窗让我参考一下就行了:)

客户端和服务器的消息同步问题:

  • 咱们的c/s通讯采用的是短链接,虽然是基于tcp的,可是彻底不可靠。客户端的消息可能丢失,服务器返回的消息也可能丢失,而双方必须能感知到消息是否丢失,不然就无法玩了。
  • 方案,给每一个消息加上序列号。客户端从序号1开始发送消息,服务器从0开始对收到的消息计数。服务器收到每一个玩家的第一个消息序号必须是1,而后服务器序号自增1,这样客户端下一个消息就是2,保证客户端序号始终是服务器序号+1 。
  • 这样若是客户端序号大于服务器序号+1,服务器就能判断出来客户端丢包,这时,客户端发来的任何消息都不处理,返回“服务器丢包消息”并带上服务端的当前序号。客户端收到“服务器丢包消息”后比较序号,回退到序号+1消息重发(须要缓存消息队列)。客户端重发的消息将和服务器序号对应上。
  • 若是客户端序号等于服务器序号,服务器就认为客户端重发了已经处理的消息(说明服务器返回的消息丢包),那么服务器直接返回上次的消息便可(服务器老是缓存上一条发出的消息)。
  • 其余状况都视为逻辑错误。

事件累加计数法和事件更新计数法

  • 如今手游中的任务系统、成就系统,全部的达成条件均可以视为事件计数问题。因而我作了一套事件系统,任务、成就生成后所有注册到事件系统中,事件触发后就给注册了此事件的全部任务、成就计数+1(也可能不是1,当成参数传给回调函数就好了)。计数达成后,认为任务、成就完成。
  • 那么问题来了,上面的事件计数方案是创建在先生成任务后发生事件的基础上的,若是反过来先发生事件后生成任务就傻逼了。好比咱们的主线任务玩家的成长是一条主线,10级的任务完成后,不领取奖励,这个任务就永远不消失,后面成长到15级的任务就不会出现。
  • 为此就须要事件更新计数法,也就是事件发生的时候对应的任务去刷新其关心的计数值。好比上例中玩家14级的时候领奖10级的任务,这时刷出了15级任务,这个任务就先刷新一次计数,获得14,任务没完成。等到下次升级事件发生,任务再刷新一次计数,获得15,任务完成。固然前提是更新计数的值是一个全局惟一可获取可累加的值,若是是挑战竞技场100次这种条件先挑战过99次后出来了任务,除非单独记录这个次数不然是搞不了的。
相关文章
相关标签/搜索