農曆七月遊戲開發靈異事件:見鬼了的Android計算錯誤

手上負責的專案目前開發到快要上市的階段,每天都不停的在處理Bug和調整,希望能讓遊戲在見人的時候能有更好的表現。在這個階段,專案成員們都為了處理各式各樣的Bug忙得不得了。套一句《東京玩具箱》裡名言『遊戲的開發呀,有一半以上的時間都是耗在與Bug纏鬥。就像打地鼠遊戲一樣,不管你再怎麼打,它還是會繼續冒出來。』

東京玩具箱第2集_004-005_1

最近專案將測試的版本交付給品保部門,請品保部門也協助進行測試。結果上個星期,品保部門回報了一條測試的Bug『遊戲中卡片學習技能需要花費的金錢與文件不符』。負責的這個專案是市面上流行的卡牌類的遊戲,遊戲中玩家可以將某張卡片上自己喜歡的技能『轉』到另一張卡片上,這個過程我們稱之為學習技能。學習技能所需的費用是一條簡單的公式,根據卡片上的某些數值來計算出學習時所需要花費的金錢。

這個公式也沒有很複雜,不過就是卡片的稀有度三次方乘上1000。品保部門測試時發現有錯的是要將一張稀有度3的卡片上技能轉到另一張卡片時,發現顯示所需金錢和文件上這個公式計算出來的結果不同。照公式來算,所需金錢應該是3*3*3(稀有度三次方)乘上1000,也就是27000。但是,品保部門測試時卻發現手機上顯示的所需金錢是26000。

接到品保部門的回報後,首先要認的就是文件上寫的公式沒有錯誤,接下來負責的企劃在電腦上開啟Unity專案測試,發現顯示的金額是正確的,並沒有品保部門所回報的狀況。於是拿測試機安裝了交給品保部門的版本,實際的測試了一下也都是正確的。由於品保部門有提供錯誤的截圖,這個測試時出現的錯誤並不是錯覺,因此自然要繼續追下去。

專案的企劃帶著測試機跑去找品保部門確認,經過一番測試後發現在部份的手機上的確有這個顯示數字不正確的狀況。老實說,如果全部的手機都出現一樣的狀況,這樣的問題反而比較好解決。但是像是這樣部份手機正常;部份手機不正常的狀況最是讓人頭痛。

再進行一番測試之後,我們確認了這個數字不正確的狀況只發生在手機這一端,實際上伺服器的一端扣除的金錢是正確的,換句話說伺服器那一方的計算是沒有問題的。為了某些安全上的原因,在我們的設計上手機端計算所需金額是用來顯示給玩家看的,實際要扣除多少錢在伺服器的這一端是會自行計算,以避免玩家修改封包傳到伺服器造成問題。

確認了問題只出現在手機這一端之後,首先我們懷疑會不會是手機上安裝了什麼程式造成的問題。不過,就算是將手機重置回到出場的狀況,這個問題還是一樣會發生。而經過這一連串的測試後,我們發現會出現這個問題的是某幾台固定的手機,而其中就包含了韓國大廠S牌以及國內某H牌。這兩支手機都是滿新的手機,市佔率也有一定的比例,因此我們不能選擇遊戲不支援它來閃避這個問題。

詢問品保部門,之前公司其他的專案在測試的時候是否有出現過這樣的問題,當時的想法是如果有的話,那麼我們可以透過其他專案的經驗來解決問題。但是很可惜的,據品保部門表示並沒有其他的專案遇到這狀況。我們向公司內的其他專案詢問,大家也不知道這個問題是怎麼一回事。

這個時候,品保部門在網路上找到了一篇『Android 計算機錯誤』的文章,裡面講到因為十進位與二進位的轉換,在Android上的確有出現過某些計算錯誤的狀況。而其中最有名的案例就是『14.52-14.49=0.029999999』這個狀況。這個闇例給了我們一點提示,讓我們開始尋找解決這個問題的方法。

Android 計算錯誤

在我們的公式中,因為有三次方的計算,因此程式使用了某個計算次方用的函數。我們請程式稍微修改一下公式裡的計算方式,把那個函數拿掉直接用變數相乘三次。結果 …. 在原本會出現顯示數值錯誤的那些手機上,終於出現了正確的數字。換句話說,如果使用了這個函數,那麼同樣的公式、數字在不同的Android手機上的確會出現不同的計算結果。

在遊戲產業待了很久,雖然說遊戲產業也算是高科技產業,不過待久了就會發現大家其實還挺迷信的。像是『機房裡放乖乖』這說法,是真真實實的存在的。原本出現這個回報的時候,我們還在想說該不會是農曆七月我們忙得忘了拜拜,所以才出現這個靈異現象。結果,原來是該死的Android手機在作祟呀 (苦笑)

  • 黃彥程

    以浮點數來說,其實運算中所記錄的數值是以[可由2除盡的數值(例:0.5,0.25,0.125)]做紀錄,因此如果兩個浮點數相減時,如果不是上述的數值就會造成誤差現象,最簡單的作法有兩種,N位後無條件進位,或如版主所述,直接透過相乘得出結果。

  • V字龍(Vdragon)

    如果方便的話可以請您協助回報一下問題給 Android Open Source Project(AOSP) 嗎?感謝