游戏数据埋点二三事
1. 什么是數據埋點
數據埋點是一切數據分析的基石。它指在特定的程序功能被觸發時,將這個行為記錄下來。例如,當玩家登錄時,記錄登陸行為;在購買時記錄訂單等。當這些行為不被記錄時,數據分析是沒有任何基礎數據可以分析的。
數據埋點就是解決在處理當程序功能被觸發時,應該如何記錄這個行為并通過合適的渠道上報的問題。
2. 游戲數據的分類
按照服務的對象分類可以分為:運營數據和產品個性化數據。
運營數據(質量數據)用來監測產品的健康程度,收益效益。例如活躍情況,收入情況等等。
產品數據往往著力于產品自身的設計驗證,玩法驗證以及數值平衡調整的內容。
按照數據的時間屬性分類可以分為:流水數據和狀態數據。
簡而言之,流水數據是每一次行為的歷史存檔,例如A玩家擊殺了B玩家1次;狀態數據是一種狀態數值,例如A玩家當前的擊殺數是1。
在接下來的關于數據埋點的內容中,主要涉及的是針對游戲產品內容設計的數據埋點相關內容。質量指標(運營數據)應當采用公司規定通用的數據指標的埋點方式和上報定義。
3. 游戲數據分析的基本流程
在進行游戲產品的數據分析時一般會遵循下面的流程。
數據設計中就包含了數據埋點與數據上報路徑的處理。游戲的功能開發結束后,數據埋點的開發就應該提上日程。最后在數據分析時通過數據清洗、篩選、提取、分析的步驟得到相關的結論來驗證設計,或為下一個設計方案提供支撐。
在首次分析數據的過程中不斷優化下來的數據處理方式就會逐步的制作成標準的數據處理流程。使用自動化腳本(洛子系統),idata服務(創建經營分析頁面)來方便需要重復分析或長期監控的數據分析需求。
4. 數據埋點的基礎原則
數據埋點時我們需要遵循一些原則,這些原則與APP數據埋點類似。
在真正進到數據埋點之前,負責數據埋點的同學可以從兩個方面著手了解。一個是數據庫系統的基礎知識,另一個是對業務功能機制穿透性的理解。
1. 了解一些數據庫內容
1.1?? 信息與數據
眾所周知信息與數據是有一定的關系的,那么數據埋點的同學就需要能夠從信息中拆解出數據,也需要能夠從數據中還原出信息。
舉個例子,張三今晚在李四家吃飯,這個行為信息變成數據就是:
人物 | 時間 | 地點 | 吃飯行為 |
張三 | 今晚 | 李四家 | 1 |
?
也就是張三今晚在李四家吃了1次飯。
在策劃描述自己想要了解到的數據指標時,策劃往往會不夠深入的去拆解本身的數據,而是描述一個經過計算后的數據指標,或者是趨勢信息。這時候數據側就需要拆解出組成指標或信息的基礎數據是什么,進而進行埋點。
為了更好的理解信息與數據,舉個例子:策劃需要了解到武器的命中率以此來判斷武器的性能是否滿足設計的要求。
那么他提出的數據需求就是:
“武器的命中率是多少?”
那么對于數據來說,要得到命中率的數據時,它首先要得到:
“命中次數、開火次數”
而對于在游戲中發生的程序功能來說,它描述的行為信息的記錄是:
“玩家使用某個武器在某個時間某個地點開火,這次開火是否被命中,命中了什么物體。”
假設玩家在單局游戲里使用AK開火10次,命中6次,那么相對應的程序的行為流水記錄應該是:
人物 | 時間 | 地點 | 武器 | 是否開火 | 是否命中 |
玩家A | ? | ? | AK-47 | 1 | 1 |
玩家A | ? | ? | AK-47 | 1 | 0 |
玩家A | ? | ? | AK-47 | 1 | 0 |
玩家A | ? | ? | AK-47 | 1 | 1 |
玩家A | ? | ? | AK-47 | 1 | 0 |
玩家A | ? | ? | AK-47 | 1 | 1 |
玩家A | ? | ? | AK-47 | 1 | 1 |
玩家A | ? | ? | AK-47 | 1 | 1 |
玩家A | ? | ? | AK-47 | 1 | 1 |
玩家A | ? | ? | AK-47 | 1 | 0 |
經過數據埋點設計統計后上報單局游戲數據記錄則是:
人物 | 武器 | 開火次數 | 命中次數 |
玩家A | AK-47 | 10 | 6 |
很顯然可以得到命中率是60%。但在這個例子中,通常為了節省上報數據的性能,行為記錄按上報的時間節點被統計成一個階段結果來上報,得到這個數據的同時,一些信息(時間、地點)被丟失了。
1.2?? 關系型數據庫和范式
我們埋點的數據和數據分析使用的數據都是基于關系模型(ER模型)建立的關系型數據庫,關系型數據庫有著自己的范式原則。(具體的知識請自行查閱。)
了解關系型數據庫的范式原則對設計數據埋點上報時的數據表結構會起到非常重要的作用。范式也會避免數據表設計中出現的一些奇怪的問題。
這里淺顯的將前3個關系范式解釋一下:
● 關系數據庫是一個只有第一行定義每一列數據意義的EXCEL表;
●?它每一列都有唯一標識可以查詢,且不可以重復;
●?在有多個從屬關系的情況下,最好依照關系拆分成多個表。
以武器統計表為例,記錄如下信息
一個AK在裝配了A、B兩個配件情況下開火6次。
一個M4在裝配了B配件開火3次。
我們來看下面兩個表結構設計:
表1:
武器 | 配件 | 開火次數 |
AK | A | 6 |
AK | B | 6 |
M4 | B | 3 |
表2:
武器 | 是否裝配件A | 是否裝配配件B | 開火次數 |
AK | 1 | 1 | 6 |
M4 | 0 | 1 | 3 |
表1的結構會明顯的在統計數據時造成數據錯誤,因為配件A、B是兩個并列的關系。
而表2的結構會隨著裝配情況的變化而不斷的增加字段或增加每次上報的數據記錄,“是否裝配A”+“是否裝配B”的組合成為了開火次數的組合主鍵。
2. 充分、深入、貫穿且宏觀的了解需要埋點的業務
進行數據埋點的同學一定要向著全面了解埋點的業務功能而努力。因為數據埋點的本質就潛藏在業務功能邏輯之中。同時數據的定義也依賴業務的功能邏輯。
舉個例子,我們假設武器命中率是指在攻擊確定目標時的命中率。在無法獲得開火朝向的數據采集中,命中率這個武器性能指標僅在一定程度上有意義,它一定小于定義中的武器命中率,因為玩家無意義的開火也被統計在其中。那么在進行數據解釋和數據分析的過程中,數據側需要明確的清楚這些類似的問題。
這類問題會產生的數據理解歧義,數據上報失敗的情況會非常多!!!!!!
因此,數據埋點設計一定需要策劃、程序、數據多方共同參與討論。
終于進入到數據埋點的策略,主要來自工作經歷后對數據的理解,若有錯漏歡迎指出。
1. 游戲數據的本質
首先讓我們理解一下游戲數據的本質,也就是描述行為信息基本四要素:時間、人物、地點、事件。
時間:客觀時間與時機。客觀時間是系統的記錄時間,而時機分為觸發記錄的時機和上報數據的時機
人物:發生行為的主體。例如,玩家角色,工會,道具,團隊等
地點:發生行為的環境。可以是游戲模式,也可以是其他字段條件
行為:被記錄下來的事件數據本身
2. 明確上報時機
數據埋點時選擇的上報時機十分的重要。合理的選擇記錄數據的觸發時機,并在考慮性能的情況下適當的選擇上報的時機。這一點需要策劃、數據、程序三方重點溝通討論記錄某個行為信息的上報時機。因為它不僅僅涉及到數據的有效性,數據定義本身,還涉及到數據上報產生的性能消耗等諸多內容。
以吃雞類的單局組隊情況下的戰績上報為例,當上報時機是某個玩家死亡時,上報的戰績中得到的排名為該玩家相對于局內所有玩家的排名(死亡順序),而真正在戰績部分展示的小隊排名,需要等待其隊友結束游戲時才能得到。這時就需要根據表的服務對象設計不同的表格來處理對數據的實時性要求。
在面對單局中大量的玩家行為時,如果在每一個行為發生時都上報數據,勢必會造成上報帶寬的堵塞以及客戶端響應速度的延時。這對于有著較高的延時要求來說的游戲是致命的。因此就需要將觸發記錄記錄在本地,并統計計算后在某一個空閑時機記錄上報,例如物品拾取操作的統計結果,或前文提到的武器使用情況這類的數據。
3. 靈活選擇記錄數據主體
當需要記錄玩家的擊殺信息,如果所有的擊殺數據都在該玩家游戲結束時上報,對于單局玩家數量較多的游戲來說。單次上報的數據量條數=?該玩家擊殺數據的人數,那么這種“一對多”的上報的數據量就有可能超過數據上行帶寬而導致數據丟包。而如果選擇記錄被擊殺信息記錄這個擊殺信息,只需要通過查詢擊殺者信息,就可以統計得到某個玩家的擊殺信息。而在被擊殺玩家死亡時上報的數據占用就只是一次發送一條記錄而已。
大部分情況下,我們的數據信息都會與玩家綁定相關,因為最終的數據分析是圍繞著玩家的游戲行為的。適當的轉換記錄行為的主體就可以起到節省帶寬同時規整數據表結構框架的作用。
4. 設計數據表的字段戰爭
4.1?? 留意字段間的從屬關系
在設計數據的表結構時,需要留心字段定義的值屬性與組別屬性的轉換問題,也就是字段定義的從屬關系,涉及靈活的遵循范式的問題。
假設一個武器需要上報不同距離下的命中率表現,那么想當然的就是,某個武器在某個距離下的開火次數和命中次數分別是多少,自然出現下面的表結構。
武器 | 命中距離 | 開火次數 | 命中次數 |
? | ? | ? | ? |
先不考慮開火次數是否能夠被統計在某個命中距離的下的問題。每一個命中次數都即從屬于這個武器,也從屬于這個命中距離,在這個表結構里“武器+命中距離”成為了記錄的主鍵,因此一把武器在每一局游戲中都有可能上報無視個記錄,而每一個命中距離記錄的數據信息都有可能是命中次數只為1。
再看下面這種類型的表結構
武器 | 命中距離>A | 命中距離<=A | 開火次數 | 命中次數 |
? | ? | ? | ? | ? |
很顯然,”命中距離<A次數”和”命中距離>=A次數”是沒有從屬關系的,它們都從屬于武器。那么這樣的表就不會產生多條冗余的記錄。這一點與之前所說的了解范式相通。
4.2?? 巧用二進制標識
在需要使用一個字段來記錄狀態時,例如玩家的死亡原因,我們通常會采用數值替換的方式,例如當值為1表示玩家被槍擊殺,2表示跌落死亡,3表示載具碰撞死亡等。在標記狀態時,我有時候會遇到在該字段需要擴展出一個維度的情況。
考慮玩家之間的關系問題。假設玩家之間有好友關系、微信好友關系、師徒關系、QQ好友關系、情侶關系、基友關系等,我們自然的就會想到要用一個字段來標識玩家的關系,因此這個關系數據就會被記錄為
玩家1 | 玩家2 | 關系標識字段 |
? | ? | ? |
關系標識字段:
當=1時,表示微信關系
當=2時,表示QQ關系
當=3時,表示師徒關系
……
?先不考慮玩家A、B之間順序對調后重復記錄的問題。玩家與玩家之間的關系種類中,既有互斥的關系也有不互斥的關系。對于互斥的關系,我們使用一個關系標識字段來表示記錄,而不互斥的關系就很難被表達出來。
?面對這個問題,我們可以采用擴展字段數量的方式來特殊標記,讓每一個標識字段對應一個關系的有無。比如
玩家1 | 玩家2 | 關系標識字段1 | 關系標識字段2 | 關系標識字段3 | …… |
? | ? | ? | ? | ? | ? |
?
這樣的方式會增加開發新字段、數據表更新入庫的工作成本。
面對這個問題我們還可以使用二進制的方式來在字段內打開一個新的標識維度來處理同時存在的狀態。
設計一個N位的二進制標識;
第一位代表好友關系
第二位代表微信好友關系
……
那么以同時為好友、師徒、情侶、微信關系為例,一個8位的二進制關系標識值就是:
好友 | 師徒 | 情侶 | 微信 | 基友 | 戰隊 | 保留位 | |
1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
轉換為十進制int值就是=240
在數據表中的體現就為:
玩家1 | 玩家2 | 關系標識值 |
A | B | 240 |
4.3?? 利用最大字段大小
一般來說tglog數據上報中一般會將字段作為string值和int值存儲。單個字段大小不能超過32KB,一條記錄大小不能超過64KB。那么對于字段設計來說,我們為了避免產生多條記錄的情況在有些情況下可以嘗試將大量的連續有規律的信息記錄在一個字段內。在數據提取出來后再進行分割處理。
例如玩家好友的關系信息。對于每兩個玩家來說,他們之間的關系都是互相作用的。因此在記錄關系時,我們需要指定二者中的一個記錄主鍵,另一個作為記錄的屬性。比如在個人戰績中展現隊友與個人戰績主體的關系。
確定了從屬關系的數據表結構其含義就會變為“該條記錄是玩家A的好友信息,他的好友是B”而不是“A和B是好友關系”。
玩家1 | 玩家1的好友1 |
A | B |
在通過A查詢A的好友都有那些玩家時,我們沒有辦法動態延展表的結構(即在表的末尾新增位置,當然可以通過固定限制好友數量的方式來解決這個問題)
那么實際上我們可以充分利用單個字段的容量大小。
?將“玩家1的好友1”設計成一個string字段,并記錄一段包含好友信息的長字符串,用特定的符號分割每一個好友的信息。
玩家1 | 玩家1的好友們 |
A | B,C,D,E,F…… |
若以玩家的角色ID進行記錄,每個角色長度為11位,加上英文逗號1位。
那么32KB可以存儲的好友個數=32*1024/(11+1) ≈ 2730個好友。
4.4?? 合并表結構
如果嚴格依照關系范式來設計數據表,對于一個產品我們可能會有很多個數據表結構。在執行數據處理提取時,需要不斷的在各個表之間關聯取交集查詢。這樣在執行數據提取時就會進行大量的循環重復查詢。相應的時間成本就會偏高。這個時候就需要結合表的服務對象來合并表結構
例如玩家的組隊信息與單局戰績是兩個表。
組隊表:
隊伍ID | 隊員1 | 隊員2 | 隊員3 | 隊員4 |
12345 | A | B | C | D |
單局戰績:
玩家ID,模式,戰績情況
玩家ID | 模式 | 戰績情況 |
20001 | 1 | X |
在面向對外平臺的戰績相關的數據應用或組隊活動的查詢時,為了能夠實現戰績的實時輸出,單局戰績與組隊信息就可以合并成為一張表,以減少生成實時查詢結果時的查表時間。
玩家ID | 模式 | 戰績情況 | 隊伍ID | 隊員2 | 隊員3 | 隊員4 |
20001 | 1 | X | 12345 | B | C | D |
在有些情況下將記錄拆分為兩個不同的表格以應對上報時機或者是性能方面的考慮也是要視情況設計的。
總之,靈活且努力的思考高效的埋點策略,深入了解業務并和程序大佬進行深入的交流。
?
APP數據與游戲數據在查閱了一些APP相關的數據埋點文章后,我發現游戲數據與APP數據的埋點其實是同源的。對于運營數據(質量數據)來說,二者幾乎沒有差異;對于產品數據來說,APP和游戲數據的埋點在側重點和實現邏輯上略顯不同。下面將討論一下產品數據埋點的二者差異。
1. 數據側重的因果
首先APP數據與游戲數據的行為數據都是對用戶行為的觀測記錄:APP的數據埋點對于用戶行為下鉆的,在我的理解中更像是對行為誘因的追求;而游戲的數據埋點則更著重于用戶行為的結果產生的數據。
APP產品數據的基礎行為主要可以拆解為:頁面停留(曝光)和按鈕點擊。功能性的數據埋點,大部分可以通過這兩者的組合來進行追蹤式的數據埋點,或標記相關的功能觸發點。更像是“用戶行為的來源于什么。”
游戲數據就會選擇“用戶行為產生了什么后果”方式來記錄信息。舉個例子,新聞瀏覽類App更關心用戶觸達某個頁面的時間,以及來源路徑;而游戲更關心用戶開火之后,造成的傷害是多少,也就是 “用戶行為之后的結果”。
游戲數據如果從基礎觸發雖然也可以被描述為操作的組合與停滯操作的時間,但面對復雜的游戲行為和功能,這樣的組合在追溯起來比APP就更加復雜。試想一下“BABA上上下下左左右右”的這種系列的數據記錄,以及找尋對應信息含義的而產生的工作量。
2. 實現邏輯上的差異
對于產品數據來說,APP數據埋點可以拆解為兩個基礎的行為的優勢讓它可以較快且完整的建立起一套數據埋點的規范,或者是進行有較強的通用性埋點設計。而游戲數據因為游戲設計的玩法和創新層出不窮,功能設計也并非千篇一律,通常會選擇針對功能去設計埋點,很難 “一招鮮吃遍天”。
APP的數據在前端的行為埋點有以下三類方式:
功能埋點 | 將數據埋點寫在特定的功能中 |
可視化埋點 | 將數據埋點利用前端的腳本追蹤 |
無埋點 | 在一個全埋點的SDK上制作APP |
游戲數據埋點能否仿照APP數據埋點的方式呢?
對于游戲埋點來說:
功能埋點 | 游戲的功能很少帶有普適性,功能埋點相對合適。當然如果是基于一個固定模式固定玩法不斷迭代微創新的系列產品來說或許會有一個基礎的數據埋點框架 |
可視化埋點 | 游戲之間實現方式有著使用引擎不同的重大差異 |
無埋點 | 游戲功能繁復,全埋點幾乎不可實現 |
*很多質量數據已經有了基礎的SDK記錄,但針對游戲內容本身的數據埋點很少有統一的模塊。
?基于此這也是為什么游戲數據的埋點設計要與游戲功能設計一同并行的,其實這個流程還能夠簡化或像APP一樣更加的系統化和自動化。APP上使用的可視化埋點和無埋點也許會在將來隨著游戲程序框架的統一或功能框架的完善被逐步開發出來。
寫在最后
字段設計中還有很多例如數值大小在計算后越界溢出的問題也需要在數據表結構設計時就考量好。甚至有些要到了最后才會發現,因此在整個數據環節中,紅線可能是經歷最多的流程。其實往往會祈禱問題在這里集中出現,因為問題如果不在這里出現,那就會浪費一次獲得數據信息的版本機會。數據信息丟失了就不會再有彌補的機會。
?數據埋點流程圖
總結
- 上一篇: CSS干货直击:腾讯无边界访问控制体系建
- 下一篇: 腾讯技术直播间 | 走进小程序云开发