Таймер Unity не работает, когда приложение убито android - PullRequest
0 голосов
/ 28 мая 2020

Я новичок в единстве и c#, у меня есть код для увеличения энергии через 10 минут, я использовал PlayerPrefs для этого, он работает в единстве, но не работает на мобильных устройствах, пожалуйста, помогите. Я не могу понять, что именно вызывает проблему в телефоне. Также таймер приостанавливается, когда приложение не закрывается, а просто сворачивается на мобильном устройстве. Я хочу, чтобы таймер обратного отсчета продолжал работать в минимальном размере, а также в случае его смерти.

using System;
using UnityEngine;
using UnityEngine.UI;

public class EnergyAdder : MonoBehaviour
{
    // Start is called before the first frame update
    public float waitTime = 600;
    Timer timer;
    public GameRoot gameRoot;
    public int count;
    DateTime currentDate;
    DateTime oldDate;

    void Start()
    {
        //timer = new Timer(waitTime);
        float remainingTime = PlayerPrefs.GetFloat("TimeOnExit");
        timer = new Timer(remainingTime);
        if (PlayerPrefs.HasKey("sysString"))
        {
            currentDate = DateTime.Now;
            long temp = Convert.ToInt64(PlayerPrefs.GetString("sysString"));
            oldDate = DateTime.FromBinary(temp);
            TimeSpan difference = currentDate.Subtract(oldDate);
            count = (int)(difference.TotalSeconds / waitTime);
            Debug.Log("time remaining " + count);
            gameRoot.AddEnergy(count);
            timer = new Timer(remainingTime - (float)difference.TotalSeconds);
            //PlayerPrefs.DeleteKey("TimeOnExit");
            //PlayerPrefs.DeleteKey("sysString");
        }
    }

    // Update is called once per frame
    void Update()
    {
        if (Gameroot.isFull)
        {
            GetComponent<Text>().text = "Full";
            count = 0;
            timer.refresh();
        }
        else
        {
            //Debug.Log("deltatime ************************"+ secondstime);
            timer.countDown();
            if (timer.isFinished())
            {
                timer = new Timer(waitTime);
                timer.refresh();
                gameRoot.AddEnergy(1);
            }
            UpdateClock();
        }
    }

    void UpdateClock()
    {
        int seconds = ((int)timer.timeLeft) % 60;
        int minutes = (int)(timer.timeLeft / 60);
        GetComponent<Text>().text = minutes.ToString() + ":" + seconds.ToString("00");
    }

    void OnApplicationQuit()
    {
        PlayerPrefs.SetFloat("TimeOnExit", timer.timeLeft);
        var today = DateTime.Now;
        PlayerPrefs.SetString("sysString", today.ToBinary().ToString());
        PlayerPrefs.Save();
    }
}

Пожалуйста, помогите, что не так в приведенном выше коде или что отсутствует.

1 Ответ

1 голос
/ 28 мая 2020

От OnApplicationQuit

Примечание: iOS приложения обычно приостанавливаются и не закрываются. Вы должны поставить галочку «Exit on Suspend» в настройках проигрывателя для iOS сборок, чтобы игра завершилась, а не приостанавливалась, иначе вы можете не увидеть этот вызов. Если флажок «Exit on Suspend» не отмечен, то вместо этого вы увидите вызовы на OnApplicationPause.

Я подозреваю, что то же самое и с современным Android, где ваше приложение тоже не закрыто, но hibernate.

Итак, я думаю, вы могли бы использовать OnApplicationPause и OnApplicationFocus

В Android, когда включен -экранная клавиатура включена, вызывает событие OnApplicationFocus(false). Кроме того, если вы нажмете «Home» в момент включения клавиатуры, событие OnApplicationFocus() не будет вызвано, а будет вызвано OnApplicationPause().

и просто сделайте то же самое, что и вы. в OnApplicationQuit также для OnApplicationPause(true) и OnApplicationFocus(false)

и сделайте то же самое, что и в Start, также в OnApplicationPause(false) и OnApplictionFocus(true), например,

public class EnergyAdder : MonoBehaviour
{
    public float waitTime = 600;
    public GameRoot gameRoot;
    public int count;

    // already reference this in the Inspector
    [SerializeField] private Text timerText;

    private Timer timer;
    private DateTime currentDate;
    private DateTime oldDate;

    private void Awake()
    {
        // store this reference ONCE
        if(!timerText) timerText = GetComponent<Text>();
    }

    private void Start()
    {
        GetTime();
    }

    private void Update()
    {
        // Note: probably a typo? shouldn't it be "gameRoot" ?
        if (Gameroot.isFull)
        {
            timerText.text = "Full";
            count = 0;
            timer.refresh();
        }
        else
        {
            //Debug.Log("deltatime ************************"+ secondstime);
            timer.countDown();
            if (timer.isFinished())
            {
                timer = new Timer(waitTime);
                timer.refresh();
                gameRoot.AddEnergy(1);
            }
            UpdateClock();
        }
    }

    private void UpdateClock()
    {
        int seconds = ((int)timer.timeLeft) % 60;
        int minutes = (int)(timer.timeLeft / 60);
        timerText.text = $"{minutes}:{seconds:00}";
    }

    private void OnApplicationQuit()
    {
        StoreTime();
    }

    // pauseStatus is True if the application is paused, else False.
    private void OnApplicationPause(bool pauseStatus)
    {
        if(pauseStatus)
        {
            StoreTime();
        }
        else
        {
            GetTime();
        } 
    }

    // hasFocus is True if the GameObjects have focus, else False.
    private void OnApplicationFocus(bool hasFocus)
    {
        if(hasFocus)
        {
            GetTime();
        }
        else
        {
            StoreTime();
        }
    }

    private void StoreTime()
    {
        PlayerPrefs.SetFloat("TimeOnExit", timer.timeLeft);
        var today = DateTime.Now;
        PlayerPrefs.SetString("sysString", today.ToBinary().ToString());
        PlayerPrefs.Save();
    }

    private void GetTime()
    {
        // NOTE: You should consider to pass a default value like
        //float remainingTime = PlayerPrefs.GetFloat("TimeOnExit", 15);
        float remainingTime = PlayerPrefs.GetFloat("TimeOnExit");
        timer = new Timer(remainingTime);
        if (PlayerPrefs.HasKey("sysString"))
        {
            currentDate = DateTime.Now;
            long temp = Convert.ToInt64(PlayerPrefs.GetString("sysString"));
            oldDate = DateTime.FromBinary(temp);
            TimeSpan difference = currentDate.Subtract(oldDate);
            count = (int)(difference.TotalSeconds / waitTime);
            Debug.Log("time remaining " + count);
            gameRoot.AddEnergy(count);
            timer = new Timer(remainingTime - (float)difference.TotalSeconds);
        }
    }
}

Примечание: набрано на смартфоне, поэтому я не могу его протестировать, но надеюсь, что он пойдет в правильном направлении

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...