今日からすぐに使えるUnity実例集の第2弾です。
これは「他のアプリでよく見るアレ」を実装していこうじゃないかという企画ですので、そのうちあなたが求めている実装を紹介するかもしれません。是非チェックしにきてください。
スマホゲーム界隈では放置系RPGが流行っていますが、この手のゲームではアプリを開くとドッサリと報酬がもらえたりします。ゲームを起動していないのに「8時間分の報酬です」などと表示されたりしますが、これはどういう仕組なのでしょうか。
今回のポイント、放置報酬は「ゲームを閉じていた時間を正しく計算できているか」でほぼ決まります。
というわけで今回は、前回の発展形として
ゲームを閉じていた時間を正確に計算する仕組みを
Unityでコピペ実装していきます。
放置時間計算の基本方針
やることはシンプルです。
- ゲームを閉じる(またはバックグラウンドに入る)直前に
「その時刻」を保存 - 次回起動時に「現在時刻」と比較
- 差分=放置していた時間
これだけで、放置系ゲームの報酬ロジックにそのまま使えます。
実装のポイント
重要なのは2点です。
・端末の現在時刻を保存すること
・秒単位で差分を取ること
今回は扱いやすさ重視で、DateTime と PlayerPrefs を使います。
コピペで動く実装例
放置時間を管理するクラス
using UnityEngine;
using System;
public class OfflineTimeManager : MonoBehaviour
{
private const string LAST_PLAY_TIME_KEY = "LastPlayTime";
void Start()
{
CalculateOfflineTime();
}
void OnApplicationPause(bool pause)
{
if (pause)
{
SaveCurrentTime();
}
}
void OnApplicationQuit()
{
SaveCurrentTime();
}
void SaveCurrentTime()
{
string now = DateTime.UtcNow.ToString("o");
PlayerPrefs.SetString(LAST_PLAY_TIME_KEY, now);
PlayerPrefs.Save();
}
void CalculateOfflineTime()
{
if (!PlayerPrefs.HasKey(LAST_PLAY_TIME_KEY))
{
// 初回起動時
SaveCurrentTime();
return;
}
string lastTimeStr = PlayerPrefs.GetString(LAST_PLAY_TIME_KEY);
DateTime lastTime = DateTime.Parse(lastTimeStr, null, System.Globalization.DateTimeStyles.RoundtripKind);
DateTime now = DateTime.UtcNow;
TimeSpan offlineSpan = now - lastTime;
double offlineSeconds = offlineSpan.TotalSeconds;
Debug.Log($"オフライン時間:{offlineSeconds} 秒");
// ここで報酬計算に使う
ApplyOfflineReward(offlineSeconds);
}
void ApplyOfflineReward(double offlineSeconds)
{
// 例:1秒につき1コイン
int reward = Mathf.FloorToInt((float)offlineSeconds);
Debug.Log($"獲得コイン:{reward}");
// PlayerDataなどに加算する処理だったりダイアログを開いたり以下略
}
}
OfflineTimeManager.cs として保存。
このスクリプトを常に存在するオブジェクト(GameManagerなど)にアタッチすればOKです。
なぜ UTC 時刻を使うのか?
端末のローカル時刻を使うと、「時刻変更」「タイムゾーン変更」「サマータイム」などで、放置時間がズレる可能性があります。
DateTime.UtcNow を使っておけば、少なくとも「端末内では一貫した時刻」で扱えます。
※完全な不正対策をしたい場合は、サーバー時刻併用が必要ですが、今回は割愛します
放置報酬ロジックに組み込むときの注意
実運用では、上限時間を設けるのがほぼ必須です。
例えば、「最大24時間まで」「それ以上は打ち止め」などにしておかないと
「1年ぶり起動でカンスト報酬!このゲームは1年放置が最適解!!」
みたいなよくわからないことが起きます。
double maxSeconds = 24 * 60 * 60;
offlineSeconds = Math.Min(offlineSeconds, maxSeconds);
24時間で打ち止めにするなら、ApplyOfflineReward() 内にこのようなコードを追加するだけで、安全性がかなり上がります。
まとめ
放置時間の計算は、
・終了(中断)時刻を保存
・起動時に差分を取る
この2ステップだけで実装できます。
放置系ゲームでは、この仕組みがゲーム体験の土台になります。
前回/次回の記事リンク
≪ 前回の記事
次回の記事 ≫


