btn_arrowcmn-facebookcmn-tiktokcmn-twittercmn-xcmn-youtubecorroborationengineerEngineerhamburgericon-angleicon-arrow-bottom-lineicon-arrow-diagonal-01icon-arrow-diagonal-02icon-arrow-next-01icon-arrow-next-02icon-arrow-strokeicon-arrowicon-close-btnicon-externalicon-facebookicon-fukidashi-01icon-fukidashi-02icon-fukidashi-03icon-fukidashi-04icon-fukidashi-05icon-fukidashi-06icon-fukidashi-07icon-fukidashi-08icon-fukidashi-09icon-fukidashi-10icon-fukidashi-11icon-fukidashi-12icon-fukidashi-13icon-fukidashi-14icon-fukidashi-15icon-fukidashi-16icon-fukidashi-17icon-fukidashi-18icon-fukidashi-19icon-hatebuicon-instagramicon-is-index-illust-01icon-is-index-illust-02icon-is-index-illust-03icon-lineicon-linked_inicon-pinteresticon-rank-dash-offseticon-rank-frameicon-rank-no-frameicon-rank-trophy-item-01icon-rank-trophy-item-02icon-rank-trophy-staricon-triangle-01icon-triangle-02icon-twittericon-xicon-youtubeis-bg-book-01is-bg-book-02is-bg-book-03is-bg-book-04is-bg-book-05is-bg-book-06is-bg-boxis-bg-cupis-bg-desktopis-bg-flagis-bg-glassis-bg-hatenais-bg-human-01is-bg-human-02is-bg-human-03is-bg-human-04is-bg-pcis-bg-plusis-bg-smartphoneis-feature-01-lineis-font-daiis-font-gokuis-font-jiis-font-senis-footer-illust-01is-footer-illust-02is-nav-arrowis-prologue-boxlicense-foreignlicenselogo-gree

【TECH BLOG #41】ゲームにおける数値のインフレ対応

グリーエンターテインメント株式会社 エンジニア部のTAです。
今回は運営タイトルで行ったゲームにおける数値のインフレ対応についてお話しいたします。

ゲームの運営とインフレ

長期的に同一タイトルを運営していると、仕様次第なところではありますが、数値のインフレが進んでいき、スキルによるバフ等の効果でダメージ量の数値がプログラム上で計算不可能な桁数になってしまうことがあります。

例えばbigintの最大値が9223372036854775807でPHPではこのような19桁以上の数値を扱うと情報落ちや桁落ちといった情報が欠落したり、アプリケーションの不具合を起こしてしまいます。

このような問題を起こさずに計算できる数値の桁数の上限を上げていく対応を行います。

BCMath

数値のインフレ対応を実施するにあたってBCMathというライブラリを使用しました。
BCMathは任意のサイズの大きさの数字を扱うことができ、十分なメモリがあれば文字列表現で数値を処理することができるPHPで提供されているライブラリです。BCMathを用いることで数値を文字列として扱い、桁数による上限なしで数値を扱えるようになります。

ただし、無制限だとメモリの使用量やPHPのソースコードやデータベース等が原因で不具合が出かねないため、本サービスでは40桁を上限として扱うことにします。
似たようなライブラリでGMPもあったのですが、こちらは小数点以下の数値計算ができないため不採用となりました。

作業工程

開発環境へBCMathインストール

開発メンバーへインストール方法の手順を共有し、すべての開発環境にBCMathをインストールしました。

PHPコード改修・テーブル構成の変更

PHPの演算子での計算を行っていたロジックは以下のようにBCMathのbcadd(加算)、bcsub(減算)、bcmul(乗算)、bcdiv(除算)、bcmod(剰余)関数に置き換えるよう改修しなければいけません。

尚、BCMathを用いた計算結果を保存するDB領域があれば、必要に応じて保存形式を変更する必要もあります。
今回はmysqlのデータベース上に計算結果を保存するテーブルがあるため、該当テーブルの該当カラムの型をBIGINTからVARCHAR型にALTER TABLEで変更しています。

開発環境での動作検証

動作検証を行い不具合が発生しているかどうか確認を行いました。
発生した問題のケースとしては、計算ロジックの改修漏れによる計算間違いや、ゲーム画面で桁数の大きい数字を表示することでUIの崩れが多かったです。
特に桁数が多くなることで、以下の画像のようにユーザーが数値の比較ができなくなる懸念もあったため、桁数に応じて単位表示に切り替えるよう仕様変更が頻繁に行われました。(1110000000010なら1兆1100億と表示し、桁が小さい数字は表示を省略)

本番環境へBCMathインストール

BCMathのインストール作業をインフレ対応のリリース前に実施しました。
複数台あるwebサーバー全てにインストールする必要があるため、インフレ対応を行うメンテナンスの前の別日にこちらの作業を実施致します。

本番環境へリリース

PHPの改修したコードを本番環境へデプロイしました。
BCMathを用いた計算によるメモリ使用率があがり、メモリやCPU負荷が高くなる可能性があったのですが、
定常稼働しているサーバー台数を10台から14台へ増やす対策をとっていたので、問題なくリリースが完了しました。

まとめ

・ゲームのインフレ対策でBCMathというライブラリを使いbigintの扱える数値より大きい数値を扱えるようにしました
・インフレ対応による桁数の上限を解放することで、ソースコードやデータベースの改修だけでなく、画面UIやユーザビリティを考慮した仕様変更による改修も必要になります
・BCMathを使用することでメモリへの負荷が高くなるため、導入後のサーバー負荷は確認しておく必要があります

最後に

数値の桁のインフレ対応について簡潔にまとめさせていただいたのですが、
実際は数ヶ月の工数がかかった大規模改修でした。

実装コスト以上に長期的に調査コストをかけて影響範囲を調査し、結果的に影響範囲が広く検証コストも高くなりましたが、改修内容や対応手順の品質が高く、クリティカルな障害は発生せず無事にリリースできました。

サービスが開始されてから長い間運用していることもあり、こういった処理の根幹を担う機能の改修は今後も行うことになると思いますが、その都度慎重に不具合なくリリースまで持っていけるよう頑張っていきたいと思います。

グリーエンターテインメント株式会社 広報担当

東京都港区六本木6-11-1 六本木ヒルズゲートタワー

E-mail:info-ent@ml.gree.net