いぬおさんのおもしろ数学実験室

おいしい紅茶でも飲みながら数学、物理、工学、プログラミング、そして読書を楽しみましょう

ゲーム完成、アプリのバックグラウンド問題、時刻の精度の問題

 さっき、できあがったゲームをGoogleに送りました。1週間?かそのくらい、審査があるそうです。通ればそのまま公開です。こんなかんじです↓

f:id:Inuosann:20210707190728j:plain

アイコンはこれ↓

f:id:Inuosann:20210707190852j:plain

動画にしてみました。

youtu.be

 アプリ作成中、何日かに1回は何か問題が起こっていました。最後の2つを紹介しましょう。入門書には書いていないし、ネットでもこちらで起こっている問題そのままの記事はなかなかありません。みんなどうしてるんでしょうか……。

アプリの実行中にユーザーが「天気予報を見よう!」なんて思ったとき、Androidだとホームキーや三本棒のキーを使ってアプリを切り替えますよね。このとき、もとのアプリは終了するのではなく、バックグラウンドへ移ります。裏で動き続けているということです。動くと言ってもガンガン動いているわけではありません。具体的にどんな感じなのか、気になる人は次の記事をどうぞ。

www.omoshiro-suugaku.com

ユーザーがいつそういった操作(急に天気予報を見に行ったり)をするかは全く分かりませんから、こちらもそれなりに気をつかってプログラムしなければなりません。さあ今晩公開、と思ったときにLINEが来て画面の上から通知がペロッと降りてきて、それをタップしたときの挙動がおかしくてコードを見直したこともありました。今回作ったゲームはキャラクタの動作用に内部でずっと時間を測っており、バックグラウンドに移っている間は時間のカウントは止めています。その関係でトラブルが起こっていたんですが、対応はそれなりに面倒でした……。

ずっと気になっていて、とうとう最後になってしまった問題。スマホのアプリには、PCのソフトには大抵ある「終了」のボタンがありません。ぼくも何かの拍子に気づき、「あれ、ないよ?」と驚きました。さっき書いたとおりで、スマホのアプリは起動したら終了せず、使わないものはバックグラウンドへ移動しているだけなのです。今回、これが問題の原因になりました。

 ①で少し書いた時間の測定には、ゲーム内部で UnityのrealtimeSinceStartupという変数を使っています(他の方法もあります)。この変数にはアプリの起動後、何秒経ったかが格納されています。ゲームは1秒間で画面を最低でも30回くらいは描き換えていますから、描き換えは33ミリ秒くらい毎にしています。これを考えると、時間の精度が数ミリ秒程度より悪くなるともう問題が出る気がしますよね。realtimeSinceStartupはfloat型の変数で、もちろん詰め込める情報量は限られています。何しろスマホのアプリは「終了」しないのです。放っておけば起動後の時間が10万秒とか100万秒とかになります。このとき、当然精度は悪くなります。早い話、8桁の電卓で1.00076は扱えますが、1234567.5678という値は扱えません。1234567.6などと扱われることになります。左の方の桁(10の位よりも100の位、100の位よりも1000の位)が大事なのですから仕方ないのです。あまりこういう話題を扱った記事がなく、見つかったのはこれだけでした。

qiita.com

この記事によると、起動後1000秒で分解能が0.1秒、24時間で分解能が7ミリ秒程度になるとのこと(この程度の誤差が出ると思ってよい、ということでしょう)。じゃあ……というので、例えば4時間経ったらアプリを終了してしまえば安全ですよね。もちろんゲーム中にいきなり終了してはいけませんから、それは注意します。

 今さらながら、こんなことなら起動後の時間を使うのではなく、ゲーム開始時にそのときの時刻を取得し、それをもとに経過時間を測るようにすればよかったかも知れません。ゲーム開始のたびに言わばリセットされるわけで、今回問題になったようなことにはなりません。

 

 まあ、全て終わったからよし、です。まだ宣伝の作業はあるから休めませんが、気は楽になりました。今度はどんなアプリを作るか、今から考えています。