Hello,
How can I create a script that fetches time from the internet and given minutes as input it decreases that timer counter and after reaching 0, it should perform an action?
The idea is like to open a chest after 1 hour, the reason I want to check the internet time is to avoid cheating.
Also I want this script to run when the game opens or gets closed to check if 1 hour is passed or not.
Here is the script:
using UnityEngine;
using UnityEngine.Networking;
using TMPro;
public class LobbyActivities : MonoBehaviour
{
public TextMeshProUGUI countdownText;
public int minutes = 5;
public string timeServerUrl = "http://worldtimeapi.org/timezone/etc/utc";
private float secondsRemaining;
private bool isCountingDown = false;
void Start()
{
// Start the countdown
StartCountdown();
}
void Update()
{
if (isCountingDown)
{
secondsRemaining -= Time.deltaTime;
// Update the countdown text
int minutesRemaining = Mathf.FloorToInt(secondsRemaining / 60f);
int seconds = Mathf.FloorToInt(secondsRemaining % 60f);
countdownText.text = string.Format("{0:00}:{1:00}", minutesRemaining, seconds);
if (secondsRemaining <= 0f)
{
// Stop the countdown
isCountingDown = false;
// Perform the action
PerformAction();
}
}
}
void StartCountdown()
{
// Fetch the current time from the internet
UnityWebRequest webRequest = UnityWebRequest.Get(timeServerUrl);
webRequest.SendWebRequest().completed += (asyncOperation) =>
{
if (webRequest.result == UnityWebRequest.Result.Success)
{
string responseText = webRequest.downloadHandler.text;
// Parse the response to get the current time
System.DateTime currentTime = System.DateTime.ParseExact(responseText, "yyyy-MM-ddTHH:mm:ssZ", System.Globalization.CultureInfo.InvariantCulture);
// Calculate the time remaining in seconds
System.TimeSpan timeRemaining = new System.TimeSpan(0, minutes, 0) - (currentTime - System.DateTime.UtcNow);
secondsRemaining = (float)timeRemaining.TotalSeconds;
// Start the countdown
isCountingDown = true;
}
else
{
Debug.LogWarningFormat("Failed to fetch time from {0}: {1}", timeServerUrl, webRequest.error);
}
};
}
void PerformAction()
{
// TODO: Perform your action here
Debug.Log("Performing action!");
}
}
the problem here is that it outputs an error saying that âFormatException: String was not recognized as a valid DateTime.â I donât know how to fix this.
Steps to success:
-
read about how that endpoint works
-
perhaps print a sample of its output
-
learn how System.DateTime.ParseExact() works
-
compare what is coming back with what is expected and make adjustments.
Remember: NOBODY here memorizes error codes. Thatâs not a thing. The error code is absolutely the least useful part of the error. It serves no purpose at all. Forget the error code. Put it out of your mind.
The complete error message contains everything you need to know to fix the error yourself.
The important parts of the error message are:
- the description of the error itself (google this; you are NEVER the first one!)
- the file it occurred in (critical!)
- the line number and character position (the two numbers in parentheses)
- also possibly useful is the stack trace (all the lines of text in the lower console window)
Always start with the FIRST error in the console window, as sometimes that error causes or compounds some or all of the subsequent errors. Often the error will be immediately prior to the indicated line, so make sure to check there as well.
Look in the documentation. Every API you attempt to use is probably documented somewhere. Are you using it correctly? Are you spelling it correctly?
All of that information is in the actual error message and you must pay attention to it. Learn how to identify it instantly so you donât have to stop your progress and fiddle around with the forum.
1 Like
Well, have you actually checked what your âresponseTextâ variable actually contains? The URL you have in your code doesnât seem to return you a date time string but an actual website. As you can see on that website they also provide a json response which is probably the best solution. Though for that you have to use http://worldtimeapi.org/api/timezone/Etc/UTC instead. This gives you a response like this:
{
"abbreviation": "UTC",
"client_ip": "2003:ec:7704:2b00:15e4:a20d:989e:42c3",
"datetime": "2023-03-22T14:35:40.940018+00:00",
"day_of_week": 3,
"day_of_year": 81,
"dst": false,
"dst_from": null,
"dst_offset": 0,
"dst_until": null,
"raw_offset": 0,
"timezone": "Etc/UTC",
"unixtime": 1679495740,
"utc_datetime": "2023-03-22T14:35:40.940018+00:00",
"utc_offset": "+00:00",
"week_number": 12
}
which you can parse with your json parser of choice. You may grab utc_datetime or maybe just unixtime. With the unixtime you should be able to do
DateTime timestamp = DateTime.UnixEpoch.AddSeconds(unixtime);
Though I havenât tested it.
You should have noticed that when you actually open your URL (Current time in Etc/UTC, via World Time API: Simple JSON/plain-text API to obtain the current time in, and related data about, a timezone.) in your browser. So you would see that this URL returns html / a whole website.
Just for the record, you should endeavor to make this all work just by trusting the system clock.
The reason is that if people want to hack your internet clock thingy or the save files, they will anyway.
If youâre concerned about the user âhacking your save files,â or âcheating in your game,â which is playing on their computer, just donât be.
Thereâs nothing you can do about it. Nothing is secure, it is not your computer, it is the userâs computer.
If it must be secure, store it on your own server and have the user connect to download it.
Anything else is a waste of your time and the only person youâre going to inconvenience is yourself when youâre debugging the game and you have savegame errors. Work on your game instead.
Remember, it only takes one 12-year-old in Finland to write a script to read/write your game files and everybody else can now use that script. Read about Cheat Engine to see more ways you cannot possibly control this.