淺談手遊程序基本坑

淺談手遊程序基本坑


當下國內的遊戲公司應該都必定程度上參和到手遊市場了的吧?不少的遊戲開發人員都是以前頁游過來的,在程序設計和功能實現上都延續了頁遊的那一套思路方法,原則上來是對功能實現上並不存在任何的問題。可是細細分析下里面是存在着一些點能夠被優化或者說直接是坑。前端

前奏

我我的經歷過三個手遊項目,兩個卡牌一個MMO,接下來提出來的點多是會傻逼。可是我明確的知道不少項目都是比較隨意的去對待這些問題的,因此纔有了我一系列的小文章來論述這些問題。但願你們在開新項目的時候能夠儘量的避開這些底層設計控制的坑。後端

顧名思義手機遊戲,絕大多數的狀況下都是運行在手機環境下的。手機對比電腦不足之處實在是太多。這邊就圍繞着接下來的問題提出幾個關注點:緩存

  1. 手機的電量是寶貴的
  2. 手機的發熱量是要被控制的
  3. 手機的流量是寶貴的
  4. 手機網絡的延遲是不可控的
  5. 手機網絡是不穩定的

斷線重連(客戶端)

由於手機網絡的不穩定性,致使手機遊戲的頻繁的斷開、重連網絡是很是常見的現象。在頁遊時代這個行爲是一個F5(刷新)就搞定的事情,可是在手機時代這個方案明顯行不通。因此咱們有了下面這個話題:服務器

在開始這個話題以前我用wireshark工具抓包了以下幾個遊戲並簡單觀察其機制(不必定是對的)網絡

  1. 《皇室戰爭》 tcp+udp協議混合使用,主界面的操做流程是由tcp socket來控制傳輸的,戰鬥過程當中是udp協議進行數據的傳輸的。在網絡斷開的狀況下就是從新走登陸流程。
  2. 《王者榮耀》 跟《皇室戰爭》的傳輸模式基本上是同樣的也是tcp和udp聯合使用。
  3. 《暗黑破壞神2》tcp協議,由於當下用的協議就是tcp因此着重研究了該遊戲的網絡重連。

以打副本爲例子:app

  1. 若是是進入遊戲後本身主動斷開網絡,能夠繼續參與遊戲的戰鬥,直到副本結算時會彈出網絡異常請從新鏈接,點擊重連會對數據進行重發,過了5秒後若是尚未成功又彈出該界面。若是這個時候網絡鏈接上去是能夠按照正常的流程參與結算的。
  2. 在無感知的狀況下斷開前端網絡(手機不斷網,把路由器斷網):點擊打副本進不去。若是在副本里面的話能夠繼續進行戰鬥知道結算。一樣的會出現第1種那樣的狀況。
  3. 前面2中狀況說的都是服務器已經斷開鏈接的狀況,從抓包分析上看,服務器應該是3次心跳都沒有收到的狀況下回主動斷開與前端的socket鏈接。 若是在這三次心跳時間內重現網絡鏈接上去,其實先後端都認爲沒有發生過網絡異常。能夠按照正常的流程進行結算。
  4. 若是網絡鏈接失敗的狀況下,下次再網絡情況良好的地方還能夠正常的結算。
    .....

總結:socket

內容表現很是的多,我單測試這個就用了一個上午的時間,這邊也不浪費你們的時間直接來看結論和合理的設計:tcp

  1. 客戶端必須作對出去包的緩存處理。 以備用網絡鏈接斷開點擊重連時請求數據還存在。
  2. 在網絡鏈接過程當中,若是socket一直沒有斷開(前端的沒有斷),前端仍然能夠往socket發送數據,在第一次點擊重連時能夠再原socket上發送數據,若是第二次點擊重連時就應該手動把舊的socket斷開,新創建一條根服務端的socket並把緩存數據發送出去。
  3. 無論怎麼什麼狀況下,若是手機主動獲得了socket斷開的回調,就應該進入自動重連的模式,若是有重要包應該直接彈窗,不然的話就後臺本身重連,重連後當即把緩存的數據發送出去。
  4. 服務端通常會在屢次心跳未收到的狀況下主動斷開socket,以避免形成過多的「殭屍」玩家存在。
  5. 服務端作數據緩存操做,由於有可能前端發過來多個請求結算,這個時候第二個包確定是結算失敗的。因此須要從緩存中把上一次結算的時間返回給前端。

網絡中斷(服務端)

分析下網絡中斷的狀態和行爲能夠分爲以下四種:工具

  1. 玩家主動退出遊戲,網絡斷開
  2. 玩家kill掉遊戲進程,網絡斷開
  3. 玩家網絡情況糟糕頻繁的掉線重連
  4. 接電話、鑽地鐵、回覆消息等遊戲進程進入後臺的網絡斷開

從四種斷網方式中能夠判定出玩家的接下來行爲:性能

  1. 前兩種行爲若是要繼續遊戲必須從新登陸游戲
  2. 後兩種行爲切迴游戲界面就能夠繼續遊戲

對於服務器來講,除了第一種狀態下服務器知道玩家是下線狀況外,其餘的三種狀態服務器是沒法區分的,由於對於服務器來講都沒有主動收到前端的fin包(網絡中斷)的包,這也就是爲何基本上全部的遊戲都有心跳包的緣由,其實就是用來界定網絡是否還存在的狀況。

在傳統的頁遊中,主要發生了斷線行爲都是直接把數據存檔,內存數據消除。聽起來好像沒有問題,可是回去分析玩家行爲時會發現,其實後兩種行爲在切迴游戲界面時是能夠繼續進行遊戲的,這個時候若是把數據dump有兩種狀況:

  1. 內存數據直接丟失,可能形成玩家接下來的數據就異常,好比說在作刷怪任務時,可能中途有數據直接傳到服務器來保存,可是由於只是結算的時候用,因此也不會設計到入庫,這樣的狀況就比較糟糕了,玩家從新回來的時候數據就丟了,可是對於前端來講仍是正常的...
  2. 頻繁的dump數據到磁盤自己是比較耗費性能,並且也是無心義的。好比說玩家在座地鐵,可能一條線上斷網20次,那就是20次的從磁盤加載數據到內存,再從內存dump數據到磁盤。

其餘的細節就不追究仍是直接來看結論:

  1. 狀態
    對於玩家進程行爲加多一種狀態標記:dump,因此玩家最起碼有以下三種狀態:(在實際的項目中每每是遠大於這三種狀態的)
    1. offline 離線狀態
    2. online 在線狀態
    3. dump 數據緩存狀態(玩家下線了,可是數據還留在緩存中的狀態若是玩家從新登陸的話只須要把鏈接從新指向下就好)
  2. 臨時數據

    手遊狀況比較特殊,基本上能夠說全部的數據都必需要入庫處理操做好點。最容易聯想到的現象就是別人早上打開遊戲,而後home鍵到後臺,晚上再繼續遊戲,不入庫的話根本掌握不住這個時間點。臨時緩存數據也須要入庫操做,通常會加上時效性。

  3. 服務器的重連

    若是僅僅是經過socket來進行標記,服務器是沒法判斷是不是重連。也就是說走的路線都是重登錄了。因此這個時候前端跟服務器重連時必須給服務器帶過裏標記: 重連、登陸標記。服務器根據這兩個標記刷新數據、推送數據。(好比重連不須要額外推送紅點和數據,重登錄的話可能須要把上一把的臨時數據的存檔清楚)

  4. 先後端數據同步

    在後面2中狀況下(從新切回主界面),若是涉及到跨天或者活動相關的推送時是會比較尷尬的。好比說:跨天刷新數據,本來是要把緩存數據都清楚而後從新獲取,可是由於進入了後臺得不到cpu使用權就丟失了跨天的回調,致使久數據沒法刷新;活動推送若是在登陸狀態下回直接推送、重登錄也會出發推送,可是對於重連通常不會觸發推送這個點也是比較尷尬的。因此也有一些作法是作成進入後臺xx小時,同時重連的時候跟打開app的時間不在同一天都會觸發遊戲從新登陸的(kill app 重連)。

流量

流量是人民幣,若是不珍惜也會對留存形成必定的影響哦。

由於手遊開發人員廣泛來源於頁遊,頁遊這塊網絡的不須要太多的考慮的。因此前端的緩存作的是相對來講比較少,都是直接跟服務器請求數據的,可是再手遊狀況下聽起來就以爲不怎麼妥....

廢話很少說直接說結論:

  1. 合併數據包

    對數據進行合併操做,在網絡出口處,若是在一個瞬間又多個包同時推送給同一個玩家須要對包進行合併操做。 一個tcp的包頭最小20字節呀(很大),因此能合併就合併下吧。

  2. 數據前端緩存

    在協議商定時額外的帶多一個標記位,用於指定是獲取更新數據呢仍是獲取所有數據。(建議本地有緩存的狀況下都作更新數據處理),對於切tab操做(手殘黨最喜歡作),儘量的避免反覆請求。 切記:別作成每次打開界面都跟服務器拿數據。

  3. 分批按量發送

    數據分批份量來推送,避免推送大數據,最典型的表明就是排行榜、拍賣行。

  4. 數據扁平化設計

    例如把一個int數據拆出來表示多個字段的意義。

  5. 數據壓縮

    對於大於xx字節的數據包進行壓縮。

電量和發熱量

當前市場上不少遊戲插着充電線電量都仍是在減小的。也有遊戲玩一會手機就成爲了暖手爐的。
這兩個點影響流失的比率仍是比較高的。我就卸載不少這樣的遊戲。想一想你的手機本來充滿電用一天的,可是如今玩了一會遊戲就要自動關機了。想一想你用你的雙手握着一個暖爐的時候是怎麼樣感受....

那麼怎麼來下降這兩個點呢:(由於我主要是後端,這個點可能點的比較虛)

  1. 減小cpu的使用率,能夠從內存換cpu的角度上去衡量下。
  2. 減小GPU的使用,前端gpu的渲染很是耗電。
  3. 減小網絡應答,這個對比前面兩個能夠小到忽略。由於網絡也是io對cpu也是比較的耗的。

總結

這裏的結論可能並不必定都是最好的,也可能考慮到的點尚未那麼全面。歡迎前來拍磚...

(本文的結論基本上都是通過線上測試驗證過的,並非本身臆想天開得來的)

相關文章
相關標籤/搜索