ホーリーのプログラミング日記

ホーリーのプログラミング日記

エキセントリック・スーパーアプリクリエイター / アプリ総DL数 約180万 / 全然分からない 俺は雰囲気でアプリを作ってる / iOS : apple.co/3m3HxSm / Android : bit.ly/3ma0liZ

【Unity】バックグラウンドでも時間の経過を取得する方法

 

前にUnityで時間を求める記事を書いたんですが、これ盛大に間違ってましたw

アブラカタブラの難所を超えてきました - ホーリーのプログラミング日記

 

いや、ちゃんと動くんですけど、アプリがバックグラウンドになったり、また終了してしまうと、時間の取得が出来ないっていう、ポンコツ仕様だったみたいです。昨日気が付いたんですけどね。。

 

んで初心に立ち返って考えたら、何かアイディアが出てきました。

そもそも僕、PHPではそれ出来てるんですよ。ビルメンネットには、案件の掲載期日があって、時間の経過を取得していました。

また、こないだ出した「命の時間」もそうですね。あれも時間の取得がちゃんと出来ています。

 

そんなわけで、ゼロベースで考えた結果、何かが見えてきましたよ。

ここから少々分かりづらいので、根性のある方のみ、読み進めていただけると幸いです。

(読んだ結果、何かを得られる保証はありませんw)

 

まずC#で現在時間を取得する方法は非常に簡単なんですが、これをセーブする方法が分かりませんでした。

時間はDateTime型になるんですが、これをPlayerPrefs.Setなんとかでセーブする方法が分からなかったんです。PlayerPrefsに、そういう型が見つからなくて。

 

なので、PHPでやってたような、1970年1月1日から、今までの秒数を取得して、それをセーブすることにしました。

これならInt型でもいけるんで、そうしてみた次第です。

 

「基準となる時間」の、1970年1月1日からの秒数。また1970年1月1日から「現在時間」までの秒数。この2つを求めて、基準の秒数から、現在の秒数を引けば、その差分が出てくると思い、この方法を選択しました。

これ数値はマイナスになるので、−1を掛けてプラスの値にしています。

 

baseTime = new DateTime (1970,1,1);
startTime = DateTime.Now;
startdiff = (startTime - baseTime).TotalSeconds;
PlayerPrefs.SetInt ("STARTDIFF",(int)startdiff);

 

とりあえず、ゲームのタイトル画面みたいなところで、startTimeを設定します。これが基準の時間ですね。んでstartdiffが基準の秒数。

 

これを設定してる前提で、ゲーム画面へ遷移します。

 

using UnityEngine;
using System.Collections;
using System;
using UnityEngine.SceneManagement;

public class TimeManager2 : MonoBehaviour {

    int life;

    DateTime startTime;
    DateTime nowTime;
    DateTime baseTime;

    double startdiff = 0;
    double nowdiff = 0;
    double seconddiff = 0;

    double minute = 0;
    double second = 0;
    double num = 30; //秒数。

    int result = 0;

    int beforeSecond = 0; //30秒で回復するんだけど、画面遷移したときに、秒数が余ってたら、ここに入れる。これないと、常に30秒スタートになる。


    // Use this for initialization
    void Start () {
        
        life = PlayerPrefs.GetInt ("LIFE");

        baseTime = new DateTime (1970,1,1);
        if (life < 5) {
            startdiff = PlayerPrefs.GetInt ("STARTDIFF");
        } else {
            startTime = DateTime.Now;
            startdiff = (startTime - baseTime).TotalSeconds;
            PlayerPrefs.SetInt ("STARTDIFF",(int)startdiff);
        }

    }
    
    // Update is called once per frame
    void Update () {

        if (life >= 5) {
            startTime = DateTime.Now;
            startdiff = (startTime - baseTime).TotalSeconds;
            PlayerPrefs.SetInt ("STARTDIFF",(int)startdiff);
        }

        nowTime = DateTime.Now;
        nowdiff = (nowTime - baseTime).TotalSeconds;

        seconddiff = (startdiff - nowdiff) * -1;
        seconddiff = Math.Floor(seconddiff);

        if (life >= 0 && life < 5 && seconddiff > 0) {

            result = (int)seconddiff / (int)num;
            if (result >= 1) {
                beforeSecond = (int)seconddiff % (int)num;
                life += result;
                startTime = DateTime.Now;
                startdiff = (startTime - baseTime).TotalSeconds;
                if (life > 5) {
                    life = 5;
                } else {
                    startdiff -= (double)beforeSecond;
                }
                PlayerPrefs.SetInt ("STARTDIFF",(int)startdiff);
                PlayerPrefs.SetInt ("LIFE",life);

            }

        }

    }
        
} 

 

他人が見て分かるか疑問なんですが、こんな感じで実装することが出来ました。

アプリがバックグラウンドになったときはもちろん、アプリを終了させても、ちゃんと時間を取得して、ライフの回復を行っています。

ちなみにライフは5ですね。5が最大値の設定です。

 

なんとなく心配なのは、Update ()の中でセーブを行ってることですね。これ、処理重くならないかと気にしています。無知なので分かりませんが。

 

まあまあ、こんな感じで、バックグラウンドでも時間の経過を取得出来るようになったって話でした。