Skip to content

Instantly share code, notes, and snippets.

@somedeveloper00
Last active May 14, 2023 11:22
Show Gist options
  • Select an option

  • Save somedeveloper00/9f9e084085a407b8eef6992e46fd7b51 to your computer and use it in GitHub Desktop.

Select an option

Save somedeveloper00/9f9e084085a407b8eef6992e46fd7b51 to your computer and use it in GitHub Desktop.
Unity Timer Countdown system for upgrading items over a specific time span
using System.Collections.Generic;
using System;
using System.Linq;
using UnityEngine;
[Serializable]
public class UpgradeTimerManager {
public string id { get; private set; }
[SerializeField] List<Item> items = new();
static string getKey(string id) => $"UpgradeTimerManager_{id}";
UpgradeTimerManager(string id) => this.id = id;
public static UpgradeTimerManager Load(string id) {
var key = getKey( id );
if (PlayerPrefs.HasKey( key )) {
var manager = JsonUtility.FromJson<UpgradeTimerManager>( PlayerPrefs.GetString( key ) );
manager.id = id;
return manager;
}
else {
return new UpgradeTimerManager( id );
}
}
public void Save() {
var key = getKey( id );
if (items.Count == 0) PlayerPrefs.DeleteKey( key );
else {
var value = JsonUtility.ToJson( this, false );
PlayerPrefs.SetString( key, value );
PlayerPrefs.Save();
}
}
public void Clear() => items = new List<Item>();
public bool IsItemUpgrading(string id) {
var item = items.Find( item => item.id == id );
if (item == null) return false;
var finished = item.endTime < getTime();
if (finished) DeleteItem( id ); // lazy remove
return !finished;
}
public void StartNewUpgrade(string id, TimeSpan duration) {
if (IsItemUpgrading( id )) return;
items.Add( new Item { id = id, endTimeTicks = ( getTime() + duration ).Ticks } );
}
public TimeSpan GetRemainingTimeFor(string id) {
if (!IsItemUpgrading( id )) throw new Exception( "Item is not upgrading" );
return new DateTime( items.First( item1 => item1.id == id ).endTimeTicks ) - getTime();
}
public void DeleteItem(string id) => items.RemoveAll( item => item.id == id );
DateTime getTime() => new(DateTime.UtcNow.Ticks);
[Serializable]
class Item {
public string id;
public long endTimeTicks;
public DateTime endTime => new DateTime( endTimeTicks );
}
}
using System;
using System.Collections;
using UnityEngine;
public class UpgradeTimerManager_Test {
[UnityEngine.TestTools.UnityTest]
public IEnumerator UpgradeTimerManagerTestWithEnumeratorPasses() {
Debug.Log( "test started." );
var upgradeTimerManager = UpgradeTimerManager.Load( "test" );
upgradeTimerManager.Clear();
upgradeTimerManager.Save();
upgradeTimerManager.StartNewUpgrade( "A", TimeSpan.FromSeconds( 2 ) );
upgradeTimerManager.StartNewUpgrade( "B", TimeSpan.FromSeconds( 3 ) );
upgradeTimerManager.StartNewUpgrade( "C", TimeSpan.FromSeconds( 4 ) );
Debug.Log( $"remaining time for A: {upgradeTimerManager.GetRemainingTimeFor( "A" )}" );
Debug.Log( $"remaining time for B: {upgradeTimerManager.GetRemainingTimeFor( "B" )}" );
Debug.Log( $"remaining time for C: {upgradeTimerManager.GetRemainingTimeFor( "C" )}" );
upgradeTimerManager.Save();
yield return new WaitForSecondsRealtime( 1 );
// test it's save functionality
upgradeTimerManager = UpgradeTimerManager.Load( "test" ); // reload
Debug.Log($"contains 1: {upgradeTimerManager.IsItemUpgrading( "A" )}: {upgradeTimerManager.GetRemainingTimeFor( "A" )}" );
Debug.Log($"contains 2: {upgradeTimerManager.IsItemUpgrading( "B" )}: {upgradeTimerManager.GetRemainingTimeFor( "B" )}" );
Debug.Log($"contains 3: {upgradeTimerManager.IsItemUpgrading( "C" )}: {upgradeTimerManager.GetRemainingTimeFor( "C" )}" );
yield return new WaitForSecondsRealtime( 1 );
Debug.Log( $"contains 1: {upgradeTimerManager.IsItemUpgrading( "A" )}" );
Debug.Log($"contains 2: {upgradeTimerManager.IsItemUpgrading( "B" )}: {upgradeTimerManager.GetRemainingTimeFor( "B" )}" );
Debug.Log($"contains 3: {upgradeTimerManager.IsItemUpgrading( "C" )}: {upgradeTimerManager.GetRemainingTimeFor( "C" )}" );
yield return new WaitForSecondsRealtime( 1 );
Debug.Log( $"contains 1: {upgradeTimerManager.IsItemUpgrading( "A" )}" );
Debug.Log( $"contains 2: {upgradeTimerManager.IsItemUpgrading( "B" )}" );
Debug.Log($"contains 3: {upgradeTimerManager.IsItemUpgrading( "C" )}: {upgradeTimerManager.GetRemainingTimeFor( "C" )}" );
yield return new WaitForSecondsRealtime( 1 );
Debug.Log( $"contains 1: {upgradeTimerManager.IsItemUpgrading( "A" )}" );
Debug.Log( $"contains 2: {upgradeTimerManager.IsItemUpgrading( "B" )}" );
Debug.Log( $"contains 3: {upgradeTimerManager.IsItemUpgrading( "C" )}" );
upgradeTimerManager.Clear();
upgradeTimerManager.Save();
Debug.Log( "test finished." );
}
}
@somedeveloper00
Copy link
Author

somedeveloper00 commented May 14, 2023

test output:

test started.
remaining time for A: 00:00:02
remaining time for B: 00:00:03
remaining time for C: 00:00:04
--[1 second later]
contains 1: True: 00:00:00.9943653
contains 2: True: 00:00:01.9943653
contains 3: True: 00:00:02.9943653
--[1 second later]
contains 1: False
contains 2: True: 00:00:00.9897110
contains 3: True: 00:00:01.9897110
--[1 second later]
contains 1: False
contains 2: False
contains 3: True: 00:00:00.9851640
--[1 second later]
contains 1: False
contains 2: False
contains 3: False
test finished.

@somedeveloper00
Copy link
Author

somedeveloper00 commented May 14, 2023

sample saved json from the test:

{
  "items": [
    {
      "id": "A",
      "endTimeTicks": 638196595733375993
    },
    {
      "id": "B",
      "endTimeTicks": 638196595743375993
    },
    {
      "id": "C",
      "endTimeTicks": 638196595753375993
    }
  ]
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment