In this section, we will create the ServerHiScore
script to post and load the high score data from the server, which we will use in the WWWForm
class to communicate with the PHP file on the website, which I already set up. We will also create a hash key and encrypt it with the MD5 encryption to protect and check for the user before posting the score to the
database.
Before we create the ServerHiScore
script, we will need to get the MD5 encryption script to encrypt our data. Let's create the new Unity JavaScript and name it MD5.js
in MonoDevelop. Then, browse to the following link:
http://www.unifycommunity.com/wiki/index.php?title=MD5.
On this page, you will see the MD5
class for C# script and JavaScript that is written by Matthew Wegner. Go to JavaScript and copy the code and paste it in the MD5.js
script that we just created:
#pragma strict static function Md5Sum(strToEncrypt: String) { var encoding = System.Text.UTF8Encoding(); var bytes = encoding.GetBytes(strToEncrypt); // encrypt bytes var md5 = System.Security.Cryptography.MD5CryptoServiceProvider(); var hashBytes:byte[] = md5.ComputeHash(bytes); // Convert the encrypted bytes back to a string (base 16) var hashString = ""; for (var i = 0; i < hashBytes.Length; i++) { hashString += System.Convert.ToString(hashBytes[i], 16).PadLeft(2, "0"[0]); } return hashString.PadLeft(32, "0"[0]); }
This script will allow us to encrypt our string with the MD5 encryption.
We can use #pragma strict
in the Unity JavaScript to tell Unity to disable the dynamics typing var name = 5
and force us to use the static typing var name : int = 5
. This will also make it easy for us to debug because if we forgot to use the static typing, Unity will give us an error when the script is being compiled.
We will create the ServerHiScore
script to send and load the user data to the server, which is also encrypted with the MD5
.
ServerHiScore
. Then, we will double-click it to open MonoDevelop and add the following code://Setting the PHP url here public var PHPUrl : String = "http://www.jatewit.com/Packt/HiScore.php"; //Setting the hash key id public var hashKey : String = "UNITYGAMEDEVELOPMENTHOTSHOT"; private var obj_WWW : WWWForm; private var b_loaded : boolean; public function Start() : void { // Empty Check for Inspector values if( PHPUrl == "" ) { Debug.LogError( "PHP Url cannot be null." ); } if( hashKey == "" ) { Debug.LogError( "Hash Key cannot be null." ); } }
In the preceding script, we created the parameter to set the PHP URL that we will be connected to (we won't see anything if we try to view the link in our browser), set the hash key to check for the user, and create the WWWFrom
and boolean
objects to use in this script. In the Start()
function, we just checked to make sure that the PUPUrl
and hashKey
are not null.
SendScore(score : int, name :String)
function, which will take two parameters score
and name
. This function will create the WWWFrom
, set the parameter, and send it to the URL that we just assigned. Let's type the function as follows://Creating the function to send public function SendScore( score : int, name : String) : void { var w_form : WWWForm = new WWWForm(); //Telling PHP that the user is submitting the data w_form.AddField("action", "PostScore"); //Sending hash code key to prevent unwanted user w_form.AddField("hash", MD5.Md5Sum(name + "-" + score.ToString() + "-" + hashKey)); //Encrypt with MD5 //Sending the user score w_form.AddField("score", score); //Sending the user name w_form.AddField("name", name); //Start waiting for the response back from the server StartCoroutine(WaitingForResponse(new WWW(PHPUrl, w_form), null)); }
WaitingForResponse( www : WWW, callback : Function) : IEnumerator
function as mentioned previously. Let's continue from after the SendScore()
function and type it as follows://Waiting for the response back from the server public function WaitingForResponse( www : WWW, callback : Function) : IEnumerator { yield www; if (www.error == null) { Debug.Log("Successful."); } else { Debug.Log("Failed."); } if (callback != null) { callback(www.text); callback = null; } //Clears data www.Dispose(); }
GetScores()
function to load the user's score data from the server. Let's type it as follows://Getting the score from the server public function GetScores() : void { b_loaded = false; var w_form : WWWForm = new WWWForm(); //Telling PHP that the user is loading the data w_form.AddField("action", "GetScore"); //Start waiting for the response back from the server StartCoroutine(WaitingForResponse(new WWW(PHPUrl, w_form), LoadXMLData)); }
LoadXMLData(string : String)
function, which will parse the XML string data that returns from the server. We will type this script after the GetScores()
function as follows://Parse the XML data from the server public function LoadXMLData(string : String) : void { XMLParser.Parse(string); b_loaded = true; Debug.Log(string); }
//Getting User length public function GetUserLength() : int { if (XMLParser != null) { return XMLParser.UserLength(); } else { return 0; } } //Getting User Name by index public function GetNameData(index : int) : String { if (XMLParser != null) { return XMLParser.Name(index); } else { return ""; } } //Getting User Score by index public function GetScoreData(index : int) : int { if (XMLParser != null) { return XMLParser.Score(index); } else { return 0; } } //Loaded XML public function IsLoaded() : boolean { return b_loaded; }
The preceding functions get the server data from the XMLParser
(where we stored users' data that returns from the server).
HiScore.js
script to add some code in it and make it work. In the HiScore.js
script before the Awake()
function, add the highlighted code as follows:private var obj_localHiScore : LocalHiScore; //Creating the LocalHiScore Object
private var obj_serverHiScore : ServerHiScore; //Creating the ServerHiScore Object
public function Start() : void {
//Initializing
Start()
function and type the highlighted code:public function Start() : void { //Initializing e_page = Page.GAMEOVER; int_items = 10; scrollPosition = Vector2.zero; b_isClickRestart = false; b_isClickSubmit = false; //Creating a Local Hiscore Object obj_localHiScore = new LocalHiScore(); //Setting the maximum scores to show on the table & loading the local high score data here obj_localHiScore.SetMaxUser(int_items); //Creating a Server Hiscore Object obj_serverHiScore = GetComponent.<ServerHiScore>(); }
ServerHiScore
object created, we need to go to the GameoverPage()
function inside the SERVER HI-SCORE button page code, and type the following highlighted code:if (b_isClickSubmit == false) { GUI.Label(new Rect((Screen.width - 300)*0.5, (Screen.height*0.1) + 80, 300, 25), "Enter Your Name", GUI.skin.GetStyle("Text1")); //Creating the input text field to get the player name userName = GUI.TextField(new Rect((Screen.width - 240)*0.5, (Screen.height*0.1) + 120, 240, 40), userName, 8); //Submit button if (GUI.Button(new Rect((Screen.width - 240)*0.5, (Screen.height*0.1) + 200, 240, 30), "SUBMIT")) { b_isClickSubmit = true; //TODO: Submitting both local and server high score here obj_localHiScore.SaveGame(TimeScoreUI.int_currentScore, userName); //Submitting to the local score //Submitting to serverobj_serverHiScore.SendScore(TimeScoreUI.int_currentScore, userName); } } //Creating the Local Hi-Score page button if (GUI.Button(new Rect((Screen.width - 240)*0.5, (Screen.height*0.1) + 240, 240, 30), "LOCAL HI-SCORE")) { e_page = Page.LOCALSCORE; } //Creating the Server Hi-Score page button if (GUI.Button(new Rect((Screen.width - 240)*0.5, (Screen.height*0.1) + 280, 240, 30), "SERVER HI-SCORE")) { //TODO: Loading the score data from server here obj_serverHiScore.GetScores(); e_page = Page.SERVERSCORE; }
ServerScorePage()
function and replace the code as follows://Loading score from server private function ServerScorePage() : void { //Creating the background box GUI.Box(new Rect(Screen.width*0.1, Screen.height*0.1, Screen.width * 0.8, Screen.height * 0.8), "SERVER HI-SCORE", GUI.skin.GetStyle("Box2")); //TODO: Checking is the loader completed if (obj_serverHiScore.IsLoaded()) { var int_numUsers : int = obj_serverHiScore.GetUserLength(); if (int_numUsers >= maxUsers) { int_numUsers = maxUsers; } scrollPositionS = GUI.BeginScrollView (new Rect ((Screen.width - 320)*0.5, (Screen.height*0.1) + 80, 320, 180), scrollPositionS, new Rect (0, 0, 300, 30*int_numUsers)); for (var i: int = 0; i < int_numUsers; i++) { //Setting the number of the user GUI.Label(new Rect(0, i * 30, 35, 30), (i+1).ToString() + "."); //TODO: Showing the user name and score here GUI.Label(new Rect(35, i * 30, 120, 30), obj_serverHiScore.GetNameData(i)); GUI.Label(new Rect(155, i * 30, 145, 30), GlobalFunction.addCommasInt(obj_serverHiScore.GetScoreData(i)), GUI.skin.GetStyle("Score")); } GUI.EndScrollView (); //End Scroll Area } else { //TODO: If the loader doesn't complete display Loading... text GUI.Label(new Rect((Screen.width-150)*0.5, (Screen.height*0.1)+120, 150, 50), "LOADING...", GUI.skin.GetStyle("Text1")); } if (GUI.Button(new Rect((Screen.width - 240)*0.5, (Screen.height*0.1) + 280, 240, 30), "BACK")) { e_page = Page.GAMEOVER; } }
The preceding code will wait for the server to finish loading and display the users' scoreboard. If the loading didn't finish, the menu will show only the Loading... text; otherwise, it will display the users' names and scores that were returned from the server database.
ServerHiScore
script in the HiScore game object and click Play. When we die or kill all the enemies in the scene, we will be able to load the SERVER HI-SCORE board by clicking on the SERVER HI-SCORE button, and the SUBMIT button will now submit the score to the server and save the score to our local machine at the same time.We learned how to use the WWWForm
and WWW
object to post and load the high score from the server. We also used the MD5 encryption to encrypt the key before posting the data to protect it from unwanted users. Then, we used the
StartCoroutine()
function to wait for the response from the server.
First, we created the ServerHiScore
script to send and receive the user data from the server database. In the Start()
function, we checked to make sure that we have the server URL and encryption key.
Next, in the SendScore()
function, we first created WWWForm
. Then we used AddField("action", "Posting");
, which will tell PHP that we want to send the score by setting the action
to Posting
. (The action
parameter and Posting
value are set in the PHP code, which you can see in the HiScore.php
that I have attached with this code). Then, we set the hash
with the MD5 encryption value of hashKey
, set the score
, and name
to the WWWForm
object. In the last line, we use StartCoroutine(WaitingForResponse(new WWW(PHPUrl, w_form), null))
function to wait for the response from the server. The StartCoroutine()
function basically takes the IEnumerator
, which we pass to the WaitingForResponse(new WWW(PHPUrl, w_form), null)
function here. This function basically creates the WWW
object that sends our WWWForm
object to the specific PHPUrl
. It also takes the Function
to callback when it is finished.
Then, we have the WaitingForResponse()
function, which will wait for the response from the server, and check if the sending request succeeds. Then we check if there is any callback function to call. If there is a callback function, we will call it. Finally, we just clear all data by using www.Dispose()
.
Next, we created the GetScore()
function, which is very similar to the SendScore()
function except that we only send one parameter to PHP, which is action
to tell PHP that we want GetScore
. Also, in the StartCoroutine()
function, we put the callback function in the WaitingForResponse()
function, which is LoadXMLData
. This will be called after the loading is finished.
Then, we have the LoadXMLData()
function, which will call the XMLParser.Parse()
function to parse the XML string data that returns from the server, then store it in the XMLParser
class. We also created GetUserLength()
, GetNameData()
, GetScoreData()
, and IsLoaded()
to get the user data from index and check if the data has been loaded.
Then, we go back to the HiScore
script to add the function that will save and load the user data to the server database.
Finally, we applied the ServerHiScore
script to the HiScore game object in Hierarchy view to get the result we want.
In this step, we use AddField("fieldname", "value");
in WWWForm
to add the value and pass it to the server. In this function, the fieldname
mostly depends on the PHP script on the server.
We can open the HiScore.php
file that we have in this project package and take a look at the following line:
$action = $_POST[ 'action' ]; //Get request action from Unity
We will see that the word action
is the same keyword that we assigned in the AddField()
function
at the beginning of the SendScore()
function:
w_form.AddField("action", "PostScore");
It is basically the keyword that we use to communicate the value between Unity and PHP. In this PHP file, we used MySQL to set up the database on my website, so if you have your website and the database set up with MySQL, you can adjust this PHP to point to your database and put it to your website.
For more information on how to set up MySQL database on your website, you can go to the following link and download the file:
http://www.webwisesage.com/addons/free_ebook.html.
There is also a video tutorial of How to set up MySQL database, PHP, and flash, from Lee Brimelow. You can find it from the following link:
18.118.186.143