Adventures in Unity – 1.7a Highscores (Server Side)

Official_unity_logo

#1 What would I ideally like to achieve by the time I finish working today – Have a working online highscore system (backend), with the ability to display and update high scores (in-game).

#2 What’s the minimum I’d like to achieve by the close of play – Have a working online highscore system (backend).


To recap – Teaching myself Unity by building a simple game – An infinite runner.

In my opinion, with this style of game, a high score table is vital – I don’t think the game has enough content in and of itself to provide much entertainment beyond the first few plays.

A high score table provides motivation for players to return – In part to beat their own scores – But mainly to make sure nobody else has beaten them.

While a local high score table will add value to the game, I think an online high score table will do a much better job.

Fortunately there is plenty of code out there showing how to implement an online highscore table in Unity – Unfortunately there are far fewer sites showing how to implement an online high score for a WebGL game (my intended final format).

I was going to have to hack something together myself.


The highscore systems I eventually put together is fairly involved, so I’ve broken it into five separate sections;

  1. Server Side Code
  2. In-Game code structure
  3. Highscore Controller
  4. Display High Scores
  5. Add new high score.

This week;

  1. Server Side Code

Exciting stuff! 🙂


By server side code I’m referring to a location online where the highscores are stored, as well as the server side mechanisms to obtain and update the highscores.

To store the highscore I used the free hosting site 000webhost (Edit: 000webhost were terrible hosts I absolutely would NOT recommend them – currently I’m using NameCheap) – They are a hosting provider I’d not used before; but I’d noticed their name being thrown a few times when I was looking to see how to put this together. They provide a free domain, site & mySQL database – All of which were life-savers for me.

The server side code itself, I based the online highscore on the excellent ‘Server Side Highscores‘ sample from the UnifyCommunity website  – This won’t work straight out of the box, especially if you want for WebGL games – But it gave me a nice base to work from.


Following the instructions provided on the UnifyComunity Server Side Highscores page;

I created a simple mySQL highscore using my 000webhost webspace.

Important note: After creating a mySQL database – It takes a little time to actually get up and running – The website suggests a couple of minutes – For me it was a couple of hours.

Once the mySQL database is up and running, it’s time to upload the server side scripts (I used the PHP scripts).

There are three scripts provided in the UnifyComunity instructions;

  1. crossdomain.xml
  2. addscore.php
  3. display.php

crossdomain.xml

This is a required file; The Unity Manual explains ‘The Unity webplayer expects a http served policy file named crossdomain.xml to be available on the domain you want to access with the WWW class, (although this is not needed if it is the same domain that is hosting the unity3d file).

The crossdomain.xml code provided looks like this;

<cross-domain-policy>
  <allow-access-from domain="*"/>
</cross-domain-policy>

Though you may need to add ‘secure = “false”‘ parameter;

< ?xml version="1.0"?>
  <cross-domain-policy> 
  <allow-access-from domain="*" secure="false" />
< /cross-domain-policy>

This file needs to be placed in the root of the site, in the case of 000webhost that’s in the public_html folder crossdomain location


addscore.php

This is called by the game when adding a new highscore. By-and-large I used the PHP as provided;

$db = mysql_connect('mysql_host', 'mysql_user', 'mysql_password') or die('Could not connect: ' . mysql_error()); 
mysql_select_db('my_database') or die('Could not select database');
 
// Strings must be escaped to prevent SQL injection attack. 
$name = mysql_real_escape_string($_GET['name'], $db); 
$score = mysql_real_escape_string($_GET['score'], $db); 
$hash = $_GET['hash']; 
 
$secretKey="mySecretKey"; # Change this value to match the value stored in the client javascript below 

$real_hash = md5($name . $score . $secretKey); 
if($real_hash == $hash) { 
        // Send variables for the MySQL database class. 
        $query = "insert into scores values (NULL, '$name', '$score');"; 
        $result = mysql_query($query) or die('Query failed: ' . mysql_error()); 
}

Since I only want to store the top 50 scores; I added an extra operation to the end of the query ensuring only the top 50 scores are stored;

 $query = "delete from [high score table] Where id not in (select * from(select id from [high score table] order by score desc limit 50) as temp)"; 
 $result = mysql_query($query) or die('Query failed: ' . mysql_error());

resulting in;

$db = mysql_connect('mysql_host', 'mysql_user', 'mysql_password') or die('Could not connect: ' . mysql_error()); 
mysql_select_db('my_database') or die('Could not select database');
 
// Strings must be escaped to prevent SQL injection attack. 
$name = mysql_real_escape_string($_GET['name'], $db); 
$score = mysql_real_escape_string($_GET['score'], $db); 
$hash = $_GET['hash']; 
 
$secretKey="mySecretKey"; # Change this value to match the value stored in the client javascript below 

$real_hash = md5($name . $score . $secretKey); 
if($real_hash == $hash) { 
	// Send variables for the MySQL database class. 
	$query = "insert into blkrnnr_scores values (NULL, '$name', '$score');"; 
	$result = mysql_query($query) or die('Query failed: ' . mysql_error()); 
	//---
			
	$query = "delete from blkrnnr_scores Where id not in (select * from(select id from blkrnnr_scores order by score desc limit 50) as temp)"; 
	$result = mysql_query($query) or die('Query failed: ' . mysql_error()); 
} 

display.php

This script get the highscores from the database so they can be displayed in game. The code as provided returns the top 5 scores – I just amended

DESC LIMIT 5

added an extra 0 so that it would return the top 50 – Otherwise it’s a cut-&-paste from the website.

Also adding

header('Access-Control-Allow-Origin: *');

These scripts just need to be stored on the website, in a location the game can access. Since I’m hoping to use this site to manage the highscores for a number of games, I created a folder for this game – called BLK_RNR – and placed both scripts inside;

updatehighscore scripts location


So that’s almost everything. If you are building a PC game, these should be all the changes you need to make to setup the backend. However, if you want to create an online high score table for a webGL title – This setup won’t work – You’ll need to make one further edit to get everything up and running. After building a WebGL game using Unity 5, two folders will be created – Build and Release. In the build folder you’ll need find a .htaccess file which you’ll need to edit. The default the .htaccess file should look something like this;

Options +FollowSymLinks
RewriteEngine on

RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME}gz -f
RewriteRule ^(.*)\.js$ $1\.jsgz [L]

RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME}gz -f
RewriteRule ^(.*)\.data$ $1\.datagz [L]

RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME}gz -f
RewriteRule ^(.*)\.mem$ $1\.memgz [L]

RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME}gz -f
RewriteRule ^(.*)\.unity3d$ $1\.unity3dgz [L]

AddEncoding gzip .jsgz
AddEncoding gzip .datagz
AddEncoding gzip .memgz
AddEncoding gzip .unity3dgz

I stripped all the  AddEncoding lines from the file.

AddEncoding gzip .jsgz
AddEncoding gzip .datagz
AddEncoding gzip .memgz
AddEncoding gzip .unity3dgz

and added

AddType application/octet-stream .memgz .datagz .unity3dgz
AddType application/javascript .jsgz

Header set Access-Control-Allow-Origin "*"

Resulting in (you should be able to just copy and paste this);

Options +FollowSymLinks
RewriteEngine on

AddType application/octet-stream .memgz .datagz .unity3dgz
AddType application/javascript .jsgz
Header set Access-Control-Allow-Origin "*"

RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME}gz -f
RewriteRule ^(.*)\.js$ $1\.jsgz [L]

RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME}gz -f
RewriteRule ^(.*)\.data$ $1\.datagz [L]

RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME}gz -f
RewriteRule ^(.*)\.mem$ $1\.memgz [L]

RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME}gz -f
RewriteRule ^(.*)\.unity3d$ $1\.unity3dgz [L]

With this in place I am able to get a list of current high scores – and add new ones from within a Unity WebGL game.


Play the game (WebGL)

Grab a copy of the project here



Next post: 1.7a Highscores (Server Side MySQLi)

Last post: 1.6 PickUps

Contents page.


4 Replies to “Adventures in Unity – 1.7a Highscores (Server Side)”

Leave a comment