I am trying to implement a lives system in Candy Crush Saga where if you run out of lives then in 30 minutes they will regenerate. Here is the code I have so far. So, what I am doing is taking the current time of when the user runs out of lives. Then the next time they open the app I see what the time is and check to see if 30 minutes have elapsed and then refill the lives.
This is how I get the time of when the user runs out of lives.
int day = DateTime.Now.Day;
PlayerPrefs.SetInt("Day", day);
int hours = DateTime.Now.Hour;
PlayerPrefs.SetInt("Hour", hours);
int mins = DateTime.Now.Minute;
PlayerPrefs.SetInt("Minute", mins);
PlayerPrefs.SetString("CheckForNewLives", "yes");
PlayerPrefs.Save();
This is how I check to see if 30 minutes have elapsed.
string checkForNewLives = PlayerPrefs.GetString("CheckForNewLives");
if (checkForNewLives == "yes") {
int day = DateTime.Now.Day;
int hours = DateTime.Now.Hour;
int mins = DateTime.Now.Minute;
int beforeDay = PlayerPrefs.GetInt("Day");
int beforeHour = PlayerPrefs.GetInt("Hour");
int beforeMin = PlayerPrefs.GetInt("Minute");
if (day != beforeDay) {
PlayerPrefs.SetString("Num of Lives", "5");
}
if (day == beforeDay hours > beforeHour) {
PlayerPrefs.SetString("Num of Lives", "5");
}
if (hours != beforeHour) {
PlayerPrefs.SetString("Num of Lives", "5");
}
if (beforeMin <= 30) {
if (hours == beforeHour mins == beforeMin + 30) {
PlayerPrefs.SetString("Num of Lives", "5");
}
}else if (beforeMin >= 31 beforeMin <= 40) {
if (hours != beforeHour mins >= 0 || mins <= 10) {
PlayerPrefs.SetString("Num of Lives", "5");
}
}else if (beforeMin >= 41 beforeMin <= 50) {
if (hours != beforeHour mins >= 11 || mins <= 20) {
PlayerPrefs.SetString("Num of Lives", "5");
}
}else if (beforeMin >= 51 beforeMin <= 59) {
if (hours != beforeHour mins >= 21 || mins <= 29) {
PlayerPrefs.SetString("Num of Lives", "5");
}
}
}
I want to change it to be more like Candy Crush where there is a running timer and once that timer runs out then a push notification is sent saying that the lives have been regenerated. How would I change my code to do that? Right now I do not even think my code does what it is supposed to do
PLEASE HELP!! Thank you very much in advance for all of the help!
You don’t really need to store any of those PlayerPrefs for the date and time stuff. Just store a local variable of a DateTime object. Use DateTime.Now and add 30 minutes to it and store that in another variable when the player runs out of energy. Then in Application_Pause (runs when you lose focus and gain focus on the app) you set the LocalNotification to pop up at the appropriate time, when it loses focus. When it gains focus, you can check if DateTime.Now is more than the variable you stored before.
Then you can use an NGUI Label or whatever you use for UI. Display time remaining, by setting its text by getting a TImeSpan object by subtracting DateTime.Now from the “energy rebuilt” time and doing .ToString(“mm:ss”), and keep doing that every second to update the timer until time runs out. If time ran out that way, or when you first gain focus, give the player energy.
That’s how I do it.
2 Likes
Hello jerotas I have been looking all over for a good tutorial on how to implement LocalNotifications and Application_Pause into my game. There is none. Can you give me some code examples for me to work with. I am 13 years old and I need some guidance with this.
I’ll send you my code when I get home tonight 
Thank you so much! I also had a question on Hey Zap that you recommended to me in another forum post. If you could answer that also it would be greatly appreciated! Thank you again!!
I probably didn’t subscribe to that other thread. Where is it?
Here’s the code for ApplicationPause and Notifications.
private static DateTime? energyRefillTime = null;
private static void SetEnergyRefillTimer() {
energyRefillTime = DateTime.Now.AddHours(1);
var countdownTimerText = "59:59";
// display countdownTimerText somewhere!
}
void OnApplicationPause(bool loseFocus) {
if (loseFocus) {
SetAllNotifications();
return;
}
// gained focus!
CheckIfEnergyWaitTimeOver();
}
private void SetAllNotifications() {
NotificationServices.CancelAllLocalNotifications();
NotificationServices.ClearLocalNotifications();
if (energyRefillTime.HasValue) {
var notif = new LocalNotification();
notif.fireDate = energyRefillTime.Value;
notif.alertBody = "You have more energy!";
notif.alertAction = "The wait is over!";
notif.soundName = LocalNotification.defaultSoundName;
notif.applicationIconBadgeNumber = 1;
NotificationServices.ScheduleLocalNotification(notif);
}
}
public bool CheckIfEnergyWaitTimeOver() {
if (!energyRefillTime.HasValue || DateTime.Now < energyRefillTime.Value) {
if (energyRefillTime.HasValue) {
TimeSpan remaining = energyRefillTime.Value - DateTime.Now;
var timerCountdownText = string.Format("{0:smile:2}:{1:smile:2}", remaining.Minutes, remaining.Seconds);
// use timerCountdownText and display it somewhere!
return false;
} else {
// no refill time set!
}
return true;
}
RemoveNotification();
return true;
}
public static void RemoveNotification() {
NotificationHelper.ClearAllBadges();
// Add code to give player more energy!
energyRefillTime = null;
}
Call SetEnergyRefillTimer() when the player needs to start waiting (energy ran out).
Then make sure to call CheckIfEnergyWaitTimeOver() every 1 second (or more often) to update the countdown timer text. The rest should “just work”.
1 Like
So jerotas I am trying to implement your code into my app. I declare countdownTimerText like this so I could use it to display in my OnGUI function: private string countdownTimerText;
Then I copied and pasted your methods into my class like this:
private static void SetEnergyRefillTimer() {
energyRefillTime = DateTime.Now.AddMinutes(30);
countdownTimerText = "30:00";
// display countdownTimerText somewhere!
}
void OnApplicationPause(bool loseFocus) {
if (loseFocus) {
SetAllNotifications();
return;
}
// gained focus!
CheckIfEnergyWaitTimeOver();
}
private void SetAllNotifications() {
NotificationServices.CancelAllLocalNotifications();
NotificationServices.ClearLocalNotifications();
if (energyRefillTime.HasValue) {
var notif = new LocalNotification();
notif.fireDate = energyRefillTime.Value;
notif.alertBody = "You have more lives!";
notif.alertAction = "The wait is over!";
notif.soundName = LocalNotification.defaultSoundName;
notif.applicationIconBadgeNumber = 1;
NotificationServices.ScheduleLocalNotification(notif);
}
}
public bool CheckIfEnergyWaitTimeOver() {
if (!energyRefillTime.HasValue || DateTime.Now < energyRefillTime.Value) {
if (energyRefillTime.HasValue) {
TimeSpan remaining = energyRefillTime.Value - DateTime.Now;
string timerCountdownText = string.Format("{0:smile:2}:{1:smile:2}", remaining.Minutes, remaining.Seconds);
// use timerCountdownText and display it somewhere!
return false;
} else {
// no refill time set!
}
return true;
}
RemoveNotification();
return true;
}
public static void RemoveNotification() {
NotificationServices.ClearAllBadges();
// Add code to give player more energy!
energyRefillTime = null;
}
I call SetEnergyRefillTimer() like this:SetEnergyRefillTimer();
and I am calling CheckIfEnergyWaitTimerIsOver() like this:InvokeRepeating("CheckIfEnergyWaitTimeOver", 0.0f, 1.0f);
I am getting error though that says this: 1.)An object reference is required to access non-static member countdownTimerText' 2.)The variable
timerCountdownText’ is assigned but its value is never used 3.)UnityEngine.NotificationServices' does not contain a definition for
ClearAllBadges’
Remove the word “static” from the declaration of the SetEnergyRefillTimer method to fix #1.
#2 is a warning, it will go away when you actually use that variable. Won’t stop you from compiling.
#3, no idea, that compiles for me. I don’t know why it’s saying that. If you re-type the dot after NotificationServices, do you see a similar named method?
Would this be able to take the place of NotificationServices.ClearAllBadges();
→
NotificationServices.CancelAllLocalNotifications();
NotificationServices.ClearLocalNotifications();
Sure, that looks the same. Try that.
With the notifications do I need to create provisioning profiles that enable push notifications? Do I need to do anything special for push notifications?
No, because these are Local Notifications, not push notifications. There’s a difference. Don’t need to enable anything.
Hi there! So I Copy the Code and call SetEnergyRefillTimer() at start for testing and un update Called CheckIfWaitTimerOver() but is not working, here is my code.
public class Life2Controller : MonoBehaviour
{
private static DateTime? energyRefillTime = null;
public string displayTimerCountDown;
void Update ()
{
CheckIfEnergyWaitTimeOver();
}
void Start ()
{
SetEnergyRefillTimer();
}
private static void SetEnergyRefillTimer() {
energyRefillTime = DateTime.Now.AddMinutes(1);
string countdownTimerText = "00:59";
print (countdownTimerText);
// display countdownTimerText somewhere!
}
void OnApplicationPause(bool loseFocus) {
if (loseFocus) {
SetAllNotifications();
return;
}
// gained focus!
CheckIfEnergyWaitTimeOver();
}
private void SetAllNotifications() {
NotificationServices.CancelAllLocalNotifications();
NotificationServices.ClearLocalNotifications();
if (energyRefillTime.HasValue) {
var notif = new LocalNotification();
notif.fireDate = energyRefillTime.Value;
notif.alertBody = "You have more energy!";
notif.alertAction = "The wait is over!";
notif.soundName = LocalNotification.defaultSoundName;
notif.applicationIconBadgeNumber = 1;
NotificationServices.ScheduleLocalNotification(notif);
}
}
public bool CheckIfEnergyWaitTimeOver() {
if (!energyRefillTime.HasValue || DateTime.Now < energyRefillTime.Value) {
if (energyRefillTime.HasValue) {
TimeSpan remaining = energyRefillTime.Value - DateTime.Now;
var timerCountdownText = string.Format("{0:smile:2}:{1:smile:2}", remaining.Minutes, remaining.Seconds);
// use timerCountdownText and display it somewhere!
print (timerCountdownText);
return false;
} else {
}
return true;
}
RemoveNotification();
return true;
}
public static void RemoveNotification() {
NotificationServices.ClearLocalNotifications();
energyRefillTime = null;
}
}
Any Clues?
may you provide me a full script i am new for unity3D thanx in advance…
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Text;
using System;
public class LifeFunctionality : MonoBehaviour
{
//For Life Functionality
private bool isPause = true;
public Text lifeText;
DateTime currentDate;
DateTime oldDate;
private long temp;
private float StartTime;
public static int LifeCounter;
private int TimeDifference;
public int timeToAdd;
private int dividesTimeToAddAfterResume;
public GameObject pauseButton;
public GameObject resumeButton;
private float differencePlusRemainingTime;
private float totalDifferenceInSeconds;
void Start()
{
PlayerPrefs.DeleteAll();
//GAME STARTED FIRST TIME SET LIFE COUNTER TO 0
if (!(PlayerPrefs.HasKey ("LifeCounter")))
{
LifeCounter=0;
}
else if ((PlayerPrefs.HasKey ("LifeCounter")))
{
LifeCounter=PlayerPrefs.GetInt("LifeCounter");
}
//GAME PLAYER FIRST TIME AND THERE IS NO SCENE SWITCHING
if (!(PlayerPrefs.HasKey ("RunningGameTimeToAdd")))
{
timeToAdd = 0;
StartTime = Time.timeSinceLevelLoad;
}
//IF SCENE SWITCHING OCCURED , WE ARE STORING THE TIME IN timetoadd INT AND UPDATING LIFE COUNTER
else if ((PlayerPrefs.HasKey ("RunningGameTimeToAdd")))
{
LifeCounter=PlayerPrefs.GetInt("LifeCounter");
StartTime = Time.timeSinceLevelLoad;
timeToAdd=(PlayerPrefs.GetInt("RunningGameTimeToAdd"));
Debug.Log("Remaining Time On Scene Switching-Level-1------->"+ timeToAdd);
}
}
void FixedUpdate()
{
// Debug.Log((int)Time.timeSinceLevelLoad);
TimeDifference = (int)((Time.timeSinceLevelLoad+timeToAdd) - StartTime);
/* Debug.Log("totalDifferenceInSeconds---->"+totalDifferenceInSeconds);
Debug.Log("timeToAdd---->"+timeToAdd);
Debug.Log("ADD---->"+(totalDifferenceInSeconds +timeToAdd));
// Debug.Log("Time.Time---->"+(int)Time.timeSinceLevelLoad);
// Debug.Log("StartTime---->"+StartTime);
Debug.Log("Time Difference---->"+TimeDifference);*/
if (TimeDifference >= 10)
{
timeToAdd = 0;
StartTime = Time.timeSinceLevelLoad;
if(LifeCounter < 5)
{
LifeCounter += 1;
// Debug.Log("LIFE==="+LifeCounter);
}
}
lifeText.text =""+LifeCounter;
}
//THIS IS CALLED WHEN GAME IS RESUMED FROM PAUSE
void CalculateTimeDifference()
{
//Store the current time when it starts
currentDate = System.DateTime.Now;
Debug.Log("Current Date----->"+currentDate);
//Grab the old time from the player prefs as a long
long temp = Convert.ToInt64(PlayerPrefs.GetString("TimeSpent_OnApplicationPause"));
//Convert the old time from binary to a DataTime variable
DateTime oldDate = DateTime.FromBinary(temp);
print("oldDate: " + oldDate);
//Use the Subtract method and store the result as a timespan variable
TimeSpan difference = currentDate.Subtract(oldDate);
print("Difference: " + difference);
string highestPriority = difference.ToString();
//Debug.Log(highestPriority);
String[] priorityCache= highestPriority.Split(":"[0]);
int getHour;
getHour=(int.Parse(priorityCache[0]));
int hoursInSec;
hoursInSec=getHour*3600;
Debug.Log("getHour----------> "+getHour);
Debug.Log("hoursInSec----------> "+hoursInSec);
int getMin;
getMin=(int.Parse(priorityCache[1]));
int minInSec;
minInSec=getMin*60;
Debug.Log("getMin----------> "+getMin);
Debug.Log("minInSec----------> "+getMin);
float getSec;
getSec=((int)float.Parse(priorityCache[2]));
Debug.Log("getSec---------->"+getSec);
totalDifferenceInSeconds=(int)(hoursInSec + minInSec + getSec);
Debug.Log("TOTAL DIFFERENCE IN SECONDS---->"+totalDifferenceInSeconds);
differencePlusRemainingTime=(int)(PlayerPrefs.GetInt("RunningGameTimeToAdd") + totalDifferenceInSeconds);
Debug.Log("TOTAL DIFFERENCE PLUS REMAINING TIME---->"+differencePlusRemainingTime);
timeToAdd = (int)(differencePlusRemainingTime % 10);
Debug.Log("TIME TO ADD AFTER RESUME---------> "+timeToAdd);
if(LifeCounter < 5)
{
LifeCounter += (int)(differencePlusRemainingTime / 10);
Debug.Log("RESUME----> "+LifeCounter);
if(LifeCounter > 5)
{
LifeCounter = 5;
}
}
}
/* void OnApplicationQuit()
{
//Save the current system time as a string in the player prefs class
}*/
public void loadLevel1()
{
PlayerPrefs.SetInt("RunningGameTimeToAdd", TimeDifference);
Debug.Log("RunningGameTimeToAdd------>"+PlayerPrefs.GetInt("RunningGameTimeToAdd"));
PlayerPrefs.SetInt("LifeCounter",LifeCounter);
Debug.Log("Remaining Time On Scene Switching------->"+ PlayerPrefs.GetInt("RunningGameTimeToAdd"));
Application.LoadLevel("Scene1");
}
public void loadLevel2()
{
PlayerPrefs.SetInt("RunningGameTimeToAdd", TimeDifference);
PlayerPrefs.SetInt("LifeCounter",LifeCounter);
Debug.Log("Remaining Time On Scene Switching------->"+ PlayerPrefs.GetInt("RunningGameTimeToAdd"));
Application.LoadLevel("Scene2");
}
public void quitPressed()
{
PlayerPrefs.SetInt("RunningGameTimeToAdd", TimeDifference);
PlayerPrefs.SetInt("LifeCounter",LifeCounter);
Debug.Log("Remaining Time On Scene Switching------->"+ PlayerPrefs.GetInt("RunningGameTimeToAdd"));
Application.LoadLevel("Home");
}
public void level1()
{
PlayerPrefs.SetInt("RunningGameTimeToAdd", TimeDifference);
PlayerPrefs.SetInt("LifeCounter",LifeCounter);
Application.LoadLevel("Scene1");
}
public void level2()
{
PlayerPrefs.SetInt("RunningGameTimeToAdd", TimeDifference);
PlayerPrefs.SetInt("LifeCounter",LifeCounter);
Debug.Log("Remaining Time On Scene Switching------->"+ PlayerPrefs.GetInt("RunningGameTimeToAdd"));
Application.LoadLevel("Scene2");
}
public void pauseGame()
{
PlayerPrefs.SetString("TimeSpent_OnApplicationPause", System.DateTime.Now.ToBinary().ToString());
PlayerPrefs.SetInt("RunningGameTimeToAdd", TimeDifference);
Debug.Log("Remaining Time On Scene Switching------->"+ PlayerPrefs.GetInt("RunningGameTimeToAdd"));
PlayerPrefs.SetInt("LifeCounter",LifeCounter);
resumeButton.SetActive(true);
pauseButton.SetActive(false);
Time.timeScale=0;
}
public void ResumeGame()
{
LifeCounter=PlayerPrefs.GetInt("LifeCounter");
if(PlayerPrefs.HasKey("TimeSpent_OnApplicationPause"))
CalculateTimeDifference();
pauseButton.SetActive(true);
resumeButton.SetActive(false);
Time.timeScale=1;
}
}