Getting the time from a server
I need to get the time from a way that does not involve device time for my mobile game (it uses a per time reward system, currently on System.Datetime).
Here is the catch, I have 0 experience on servers, server scripting, which make me unable to follow most answers for similar questions online. I mostly only know C#. Ideally, I would like to be able to get the time from a server I do not own/maintain, and that can handle thousands (or maybe millions :))) ) of users at a time.
Answer by OzyT · May 16, 2017 at 09:55 AM
Your best bet for scaling are: Amazon's "Serverless" Technology or Google's Firebase. I personally prefer Google Firebase; that said, I am currently learning all these things, too.... but I will try to help you as much as I can from what I have done so far.
Please be aware that these steps I have done myself by trial and error ( except the cron job part, which I will apply in the coming days) with no experience of developing apps for mobile. My last app it was for a Windows machine 5 years ago. So, I am basically a newbie .
So, let's get started.
1. Getting ready - downloading stuff that we need
1.1-> You will need to go and download Firebase for Unity SDK
1.2-> Next you need to download these quickstart examples that Firebase made for Unity
1.3-> Download these examples for using Firebase Functions
1.4-> To use Firebase Functions I use nodejs, you can download it from here
2. Preparing to get your "hands dirty"
2.1. Go to Firebase and create an account. You can watch a video of how to do this on YouTube
Now that you have created a new project, you need to go to Project settings and then click add app I have chosen Android app. It seems I can not add any more attachments... anyway..
2.3. Next you need to enter an unique Android package name and a name App nickname (optional) .. I did not bother with the the Debug signing certificate SHA-1 (optional) , you can make that later... I have to make it , too; and then click Register app.
2.4. Next you will want to download the google-services.json file. This is an important file, Firebase will use this file to communicate with the database.
2.5. I still did not get to the Unity part, will get there soon. Now you will need to install NodeJs. You can read everything you need is here *under Set up and initialize Firebase SDK for Cloud Functions*
2.6. Now, go to Unity and install the firebase auth and database packages from the Firebase SDK. All the info for this here in the readme file
2.7. In Unity, go to build settings, select Android and enter in the Build ID , the id that you entered at point 2.3 (Android package name) ... something like com.myawsomeapp.FritzPeace179 or whatever :)
2.8. Create a folder and unzip the archive from point 1.2. First place to start is yourfolder/quickstart-unity/database/testapp/Assets/TestApp/
3. Getting into Unity
3.1. Go to yourfolder/quickstart-unity/database/testapp/Assets/TestApp/ and paste the google-services.json file you downloaded earlier at point 2.4.
3.2. Open the MainScene.unity located at point 2.8.
Go back to your Firebase console in your browser, go to Database and then Rules and check to see if read and write are equal to null. This means that anybody can write or read your database. Use this for testing purposes only. For deployments ALWAYS put the first rules as deny . What rules a parent has all the children inherit, and from there you can allow access to certain children ( branches) of your database separately ( anyway this does not matter right now, for testing purposes you can leave them equal to null )
You can read more about rules here.{ "rules": { ".read": "auth == null", ".write": "auth == null" } }
3.4. Now that you are able to write to your database, you can use functions to act as small snippets of code that run in the back-end. Go to https://github.com/firebase/functions-samples/tree/master/quickstarts/time-server and read the readme file. It will become clear that by simply calling the function you can now get the server time.
3.5. Now, by going to https://github.com/firebase/functions-samples/tree/master/child-count you will see how you can use functions to write to a database.
Quicktip: Please be aware that if you delete any functions in index.js when you deploy your functions with firebase deploy --only functions
your function on the server will also be deleted ( same goes with adding functions ) Quicktip 2 : Before deploying functions always check if Firebase has any problems by going to Firebase Status Dashboard
3.6. Now if you would try to combine those two ( the function that gets the server and the child added function ) you would get a function that adds the time into you database , this is what index.js would look like:
/**
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
// [START functionsimport]
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
// [END functionsimport]
// [START additionalimports]
// Moments library to format dates.
const moment = require('moment');
// CORS Express middleware to enable CORS Requests.
const cors = require('cors')({origin: true});
var cryptox = require('crypto');
var format = require('date-format');
exports.getservertime = functions.https.onRequest((req, res) => {
// [END trigger]
// [START sendError]
// Forbidding PUT requests.
if (req.method === 'PUT') {
res.status(403).send('Forbidden!');
}
// [END sendError]
// [START usingMiddleware]
// Enable CORS using the `cors` express middleware.
cors(req, res, () => {
// [END usingMiddleware]
// Reading date format from URL query parameter.
// [START readQueryParam]
let uid = req.query.uid;
// [END readQueryParam]
// Reading date format from request body query parameter
if (!uid) {
// [START readBodyParam]
uid = req.body.uid;
// uid = uid.replace(/\s+/g, '');
// [END readBodyParam]
}
// [START sendResponse]
const formatDateAndTime="MM-DD-YYYY-hh-mm-ss-SSS-a";
const formatDate="MM-DD-YYYY";
const formattedDate = moment().format(formatDate);
const formattedDateAndTime = moment().format(formatDateAndTime);
console.log('Sending Formatted date:', formattedDate);
admin.database().ref("server_values/").update({ ServerTime: formattedDateAndTime });
res.status(200).send(formattedDate);
// [END sendResponse]
});
});
// [END all]
3.7. Now you can access your function from here: https://us-central1- this_is_your_project_id .cloudfunctions.net/getservertime
, just replace this_is_your_project_id
with your own project id.
4. Adding code to your Unity3d project to read the database in real time.
This is the code I have modified to be used to read the database ( this listens to changes into the database and updates the values on the client side )
public void GetServerTime()
{
// Initialize the Firebase database:
FirebaseApp app = FirebaseApp.DefaultInstance;
app.SetEditorDatabaseUrl("https://zzzzzzzzzzzzz.firebaseio.com");
if (app.Options.DatabaseUrl != null) app.SetEditorDatabaseUrl(app.Options.DatabaseUrl);
FirebaseDatabase.DefaultInstance
.GetReference("/server_values/ServerTime")
.ValueChanged += (object sender2, ValueChangedEventArgs e2) => {
if (e2.DatabaseError != null) {
Debug.LogError(e2.DatabaseError.Message);
return;
}
if (e2.Snapshot != null ) {
ServerTime.text = "ServerTime : "+e2.Snapshot.Value.ToString();
}
};
Please be sure to change the database url from zzzzzzzzzzzzz.firebaseio.com
to your database url which you can find it if you go to your Firebase console in your browser, and click Database , it will be there in the middle of your screen .
5. OK , I am bored from all this reading , how do I automate this?
5.1. You create a cron job like shown here: https://github.com/firebase/functions-cron using App Engine Cron. 5.2. You google create cron job and select any service or use your own hosting.
Ok, so this is all what I have got for now.
This was my research , trial and error for over a month.
Please remember that I am new to Unity3D, C#, Firebase, Java, NodeJS, game development, mobile development.... ... I started learning a month ago and will be learning years to come into the future.
I hope this will help you and others.
thank you OzyT, very very very very very very very very much :D
Answer by Leaton · Nov 20, 2017 at 02:19 AM
Here is the answer I use to keep my time accurate across all devices by utilizing the internet/server time : http://leatonm.net/unity3d-internet-time-date-setup-guide-stop-time-cheat/