遊戲行業是程序員最理想的行業
我入行時間不長,工做之中也沒什麼人指點,老是犯下許多錯誤。有的錯誤是行業經驗欠缺致使的,屬於結構性錯誤;有的則是代碼規模經驗缺失致使的,屬於原則性錯誤。這兩種錯誤互爲因果,我把一些原則性的問題記錄下來,既檢討了本身也愉悅了他人。前端
遊戲開發問題篇
術語不統一問題:
- 這個問題每每是策劃不夠專業致使的。策劃作的文案,經常帶有很強的主觀臆想,用一些「情景式」、「過程式」的方法描述一個概念。
- 好比在作副本系統的時候,策劃給的術語「每一大章的每一小關裏面分前置關、普通關、精英關三種關卡」,這裏面的不少概念都沒有成文的叫法,無法對應到你們熟悉的英文,致使配表、協議中出現各類版本的術語。前端的同窗乾脆用漢語拼音了事,實在有違各類開發規範。。
- 方案,必須在配表、定協議以前先統一術語,把各類須要複雜描述的概念統一塊兒來,對應成一個簡單的單詞。好比,「第一章」裏面的
章
,叫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次後出來了任務,除非單獨記錄這個次數不然是搞不了的。