{"id":90594,"date":"2021-04-15T20:44:19","date_gmt":"2021-04-15T20:44:19","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=90594"},"modified":"2022-04-24T21:13:56","modified_gmt":"2022-04-24T21:13:56","slug":"using-mysql-unity","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/using-mysql-unity\/","title":{"rendered":"Using MySQL with Unity"},"content":{"rendered":"<p>SQL is the language of data management, and Unity is a game engine. The two seem to have very different goals, with one focusing on managing a database while the other is built primarily for the creation of video games. Can the two work together? As is so often the case in the world of programming, the answer is a resounding \u201cyes.\u201d As far as the games industry is concerned, databases are most useful in applications that require items like leader boards, stat tracking, and more. While a single-player focused adventure game may not need database integration, a massive racing game with thousands of players might.<\/p>\n<p>With this in mind, a demonstration is in order. An app will be created that can receive the high scores stored within a MySQL database as well as put new data into it. Within the app itself, the top five players and their scores will be displayed. A variety of tools will be used to accomplish this. This demonstration uses <a href=\"https:\/\/sourceforge.net\/projects\/wampserver\/\">WampServer<\/a> and <a href=\"https:\/\/www.phpmyadmin.net\/\">phpMyAdmin<\/a> to create the database, PHP for server scripts, and of course, Unity and C# for app creation. If you&#8217;re more comfortable with other database management and creation tools, then those should work just as well for this project.<\/p>\n<h2>Database creation<\/h2>\n<p>Start by creating your database. Open your database management program of choice and create a new database, giving it the name <em>highscores<\/em>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-90595\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/04\/graphical-user-interface-text-application-email-4.jpeg\" alt=\"Creating a new database in WAMP using phpMyAdmin\" width=\"509\" height=\"383\" \/><\/p>\n<p><strong>Figure 1: Creating a new database in WAMP using phpMyAdmin<\/strong><\/p>\n<p>Next, create a table containing the data needed. Since the goal is just to display the player&#8217;s name and their score, you can leave the table at that. Go into the SQL tab and enter the following SQL command to create this table:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">CREATE TABLE scores (\r\n   name VARCHAR(15) NOT NULL DEFAULT 'anonymous',\r\n   score INT(10) UNSIGNED NOT NULL DEFAULT 0\r\n)\r\nENGINE=MyISAM<\/pre>\n<p>It&#8217;s recommended that you enter in some data for testing the application. While you could simply enter five new scores within the Unity app itself, it&#8217;ll be easier to test high score retrieval if there&#8217;s already some data within the database. You can use the below SQL command to quickly add some test data.<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">INSERT INTO scores (name, score) VALUES ('John', 100), \r\n('Sally', 110), ('Phil', 90), ('Katy', 130), ('Jack', 150)<\/pre>\n<p>Now that the database is set up, you&#8217;ll need some PHP scripts to both retrieve and insert data into the database. These scripts will act something like the communicator between Unity and the MySQL database.<\/p>\n<h2>Server scripts \u2013 display.php<\/h2>\n<p>First, inside your server (this example&#8217;s file path is the WampServer folder, then <em>www <\/em>folder), create a folder named <em>HighScoreGame<\/em> for storing your PHP scripts. Then create a new PHP script called <em>display<\/em> and place it within this folder. Open the file in a code editor such as Notepad++ and enter the following code. Note that you may have to change the values of <code>hostname<\/code>, <code>username<\/code>, and <code>password<\/code> depending on your configuration.<\/p>\n<pre class=\"lang:c# theme:vs2012\">$hostname = 'localhost';\r\n$username = 'root';\r\n$password = '';\r\n$database = 'highscores';\r\n \r\ntry \r\n{\r\n\t$dbh = new PDO('mysql:host='. $hostname .';dbname='. $database, \r\n         $username, $password);\r\n} \r\ncatch(PDOException $e) \r\n{\r\n\techo '&lt;h1&gt;An error has occurred.&lt;\/h1&gt;&lt;pre&gt;', $e-&gt;getMessage()\r\n            ,'&lt;\/pre&gt;';\r\n}\r\n \r\n$sth = $dbh-&gt;query('SELECT * FROM scores ORDER BY score DESC LIMIT 5');\r\n$sth-&gt;setFetchMode(PDO::FETCH_ASSOC);\r\n \r\n$result = $sth-&gt;fetchAll();\r\n \r\nif (count($result) &gt; 0) \r\n{\r\n\tforeach($result as $r) \r\n\t{\r\n\t\techo $r['name'], \"\\n _\";\r\n\t\techo $r['score'], \"\\n _\";\r\n\t}\r\n}<\/pre>\n<p>This script is pretty straightforward. It&#8217;s just establishing a connection to the database before going through the scores table and retrieving the top five scores and their respective players. You&#8217;ll notice the echo statements at the end add in a newline and underscore. These might seem like strange additions to the results, but they will actually be used to help organize and display the results in a nice looking manner in the Unity app.<\/p>\n<h2>Server scripts \u2013 addscore.php<\/h2>\n<p>The next PHP script will be called <em>addscore<\/em>. As the name implies, this script will be responsible for adding data to the <em>highscores<\/em> database. All data that <em>addscore<\/em> tries to insert into the database will originate from within the Unity app. Like before, you may need to edit some of the variables to accommodate your specific setup. The important thing to note is the value of <code>secretKey<\/code>, which can be anything you like so long as the Unity app uses this value as well. This is because it will be used later on to create a secure hash which verifies that the scores being sent are indeed coming from the Unity app. If the Unity app uses a different value, then the script will not insert the input.<\/p>\n<pre class=\"lang:c# theme:vs2012\">$hostname = 'localhost';\r\n$username = 'root';\r\n$password = '';\r\n$database = 'highscores';\r\n$secretKey = \"mySecretKey\";\r\n \r\ntry \r\n{\r\n\t$dbh = new PDO('mysql:host='. $hostname .';dbname='. $database, \r\n           $username, $password);\r\n} \r\ncatch(PDOException $e) \r\n{\r\n\techo '&lt;h1&gt;An error has ocurred.&lt;\/h1&gt;&lt;pre&gt;', $e-&gt;getMessage() \r\n            ,'&lt;\/pre&gt;';\r\n}\r\n \r\n$hash = $_GET['hash'];\r\n$realHash = hash('sha256', $_GET['name'] . $_GET['score'] . $secretKey);\r\n\t\r\nif($realHash == $hash) \r\n{ \r\n\t$sth = $dbh-&gt;prepare('INSERT INTO scores VALUES (null, :name\r\n            , :score)');\r\n\ttry \r\n\t{\r\n\t\t$sth-&gt;bindParam(':name', $_GET['name'], \r\n                  PDO::PARAM_STR);\r\n\t\t$sth-&gt;bindParam(':score', $_GET['score'], \r\n                  PDO::PARAM_INT);\r\n\t\t$sth-&gt;execute();\r\n\t}\r\n\tcatch(Exception $e) \r\n\t{\r\n\t\techo '&lt;h1&gt;An error has ocurred.&lt;\/h1&gt;&lt;pre&gt;', \r\n                 $e-&gt;getMessage() ,'&lt;\/pre&gt;';\r\n\t}\r\n}<\/pre>\n<p>To keep things tidy, make sure this script is within the same folder as <em>display<\/em>. Once you have this code prepared, it&#8217;ll be time to open up Unity and begin creating the app that your users would use.<\/p>\n<p><strong><em>Unity App \u2013 User Interface<\/em><\/strong><\/p>\n<p>Now comes the part where the Unity app is made. This section is focused on making the user interface, which means using the editor to place buttons, input fields, and text. Start by creating a new project from the Unity Hub.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-90596\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/04\/graphical-user-interface-description-automaticall-1.jpeg\" alt=\"Creating a new project in Unity\" width=\"964\" height=\"561\" \/><\/p>\n<p><strong>Figure 2: Creating a new project in Unity<\/strong><\/p>\n<p>Any of the templates will work fine for this project, but the example here will use the basic 3D template. Give the project a name and set the location, then click the <em>Create <\/em>button.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-90597\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/04\/graphical-user-interface-application-description-2.jpeg\" alt=\"Figure 3: Project name, template, and location\" width=\"896\" height=\"484\" \/><\/p>\n<p><strong>Figure 3: Project name, template, and location<\/strong><\/p>\n<p>This app&#8217;s user interface is a little involved, consisting of nine elements total. There are two buttons, one for retrieving the top five scores from a database and the other for sending a new score. Speaking of sending, there are two input fields asking for a name and score. There will also be a few text labels, with two of them containing the names and scores of the top five players. Start by creating the elements, and then they&#8217;ll be positioned in a way that looks appealing.<\/p>\n<p>To create user interface (UI) elements, click the <em>Create <\/em>button in the <em>Hierarchy <\/em>window, indicated by the plus icon with a downward arrow next to it. From there, select <em>UI<\/em>, and then the UI element of choice. You will need five <em>Text <\/em>objects, two <em>Input Field <\/em>objects, and two <em>Button<\/em> objects.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-90598\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/04\/graphical-user-interface-application-description-3.jpeg\" alt=\"Figure 3: Project name, template, and location\" width=\"474\" height=\"612\" \/><\/p>\n<p><strong>Figure 4: Creating UI objects<\/strong><\/p>\n<p>Next, you&#8217;ll position and resize the objects. Doing this requires editing properties in the <em>Rect Transform <\/em>component, located in the <em>Inspector <\/em>window while an object is selected. Changing the values is as simple as selecting the designated field and changing the value within it. Alternatively, you can use the <em>Scene <\/em>window to click and drag objects where you want them.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-90599\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/04\/graphical-user-interface-description-automaticall-2.jpeg\" alt=\"Setting the location, size, and name of an object\" width=\"587\" height=\"280\" \/><\/p>\n<p><strong>Figure 5: Setting the location, size, and name of an object<\/strong><\/p>\n<p>Below is a table listing all the objects and the position and size values of each object you&#8217;ve just created. They have also been assigned names to help you know which object is which. If you wish to match the names, then renaming the object is done by right clicking the object and choosing <em>Rename<\/em>. Additionally, what type of object each item is will be noted in this table.<\/p>\n<table border=\"1\">\n<tbody>\n<tr>\n<td>\n<p><strong>Name<\/strong><\/p>\n<\/td>\n<td>\n<p><strong>Object Type<\/strong><\/p>\n<\/td>\n<td>\n<p><strong>Pos X<\/strong><\/p>\n<\/td>\n<td>\n<p><strong>Pos Y<\/strong><\/p>\n<\/td>\n<td>\n<p><strong>Width<\/strong><\/p>\n<\/td>\n<td>\n<p><strong>Height<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>NameResults<\/p>\n<\/td>\n<td>\n<p>Text<\/p>\n<\/td>\n<td>\n<p>-365<\/p>\n<\/td>\n<td>\n<p>50<\/p>\n<\/td>\n<td>\n<p>162<\/p>\n<\/td>\n<td>\n<p>297<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>ScoreResults<\/p>\n<\/td>\n<td>\n<p>Text<\/p>\n<\/td>\n<td>\n<p>-202<\/p>\n<\/td>\n<td>\n<p>50<\/p>\n<\/td>\n<td>\n<p>162<\/p>\n<\/td>\n<td>\n<p>297<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>NameField<\/p>\n<\/td>\n<td>\n<p>Input Field<\/p>\n<\/td>\n<td>\n<p>245<\/p>\n<\/td>\n<td>\n<p>58<\/p>\n<\/td>\n<td>\n<p>160<\/p>\n<\/td>\n<td>\n<p>30<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>ScoreField<\/p>\n<\/td>\n<td>\n<p>Input Field<\/p>\n<\/td>\n<td>\n<p>245<\/p>\n<\/td>\n<td>\n<p>-36<\/p>\n<\/td>\n<td>\n<p>160<\/p>\n<\/td>\n<td>\n<p>30<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>NameFieldLabel<\/p>\n<\/td>\n<td>\n<p>Text<\/p>\n<\/td>\n<td>\n<p>108<\/p>\n<\/td>\n<td>\n<p>58<\/p>\n<\/td>\n<td>\n<p>103<\/p>\n<\/td>\n<td>\n<p>30<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>ScoreFieldLabel<\/p>\n<\/td>\n<td>\n<p>Text<\/p>\n<\/td>\n<td>\n<p>108<\/p>\n<\/td>\n<td>\n<p>-35<\/p>\n<\/td>\n<td>\n<p>103<\/p>\n<\/td>\n<td>\n<p>30<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>InputDirections<\/p>\n<\/td>\n<td>\n<p>Text<\/p>\n<\/td>\n<td>\n<p>246<\/p>\n<\/td>\n<td>\n<p>148<\/p>\n<\/td>\n<td>\n<p>274<\/p>\n<\/td>\n<td>\n<p>51<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>SendScoreButton<\/p>\n<\/td>\n<td>\n<p>Button<\/p>\n<\/td>\n<td>\n<p>240<\/p>\n<\/td>\n<td>\n<p>-130<\/p>\n<\/td>\n<td>\n<p>170<\/p>\n<\/td>\n<td>\n<p>65<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>RefreshHighScoreButton<\/p>\n<\/td>\n<td>\n<p>Button<\/p>\n<\/td>\n<td>\n<p>-287<\/p>\n<\/td>\n<td>\n<p>-130<\/p>\n<\/td>\n<td>\n<p>170<\/p>\n<\/td>\n<td>\n<p>65<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Table 1: All UI elements and their positions and sizes<\/strong><\/p>\n<p>Now all the objects need some proper placeholder text. This can be adjusted by selecting an object in the <em>Hierarchy <\/em>window, then navigating to the <em>Text <\/em>component in the <em>Inspector <\/em>window. For <em>NameResults <\/em>and <em>ScoreResults<\/em>, those can be left with empty text for now. You&#8217;ll need to edit their placeholder text for the input fields, which is found by clicking the arrow next to their name in the <em>Hierarchy<\/em>. This brings up all child objects found under the parent.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-90600\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/04\/text-description-automatically-generated.jpeg\" alt=\"Revealing child objects\" width=\"258\" height=\"194\" \/><\/p>\n<p><strong>Figure 6: Revealing child objects<\/strong><\/p>\n<p>Find <em>Placeholder<\/em>, then edit the text to say \u201cEnter Player&#8217;s Name.\u201d Do the same with <em>ScoreField<\/em>, but the text should say \u201cEnter Player&#8217;s Score\u201d instead. Next, find the text objects being used to label the input fields, and change their text to reflect which field is being edited. For <em>InputDirections<\/em>, you&#8217;ll ask the player to \u201cEnter a New Score!\u201d To make it stand out a little more, adjust the font size property to thirty for <em>InputDirections<\/em>. Finally, the text for the buttons should be changed to better indicate what the buttons do. Starting with the <em>SendScoreButton <\/em>object, click the arrow next to it to show the child <em>Text <\/em>object. Enter the text \u201cSEND SCORE\u201d and fill in the button by adjusting the text size to twenty-five. As for the <em>RefreshHighScoreButton<\/em>, that button&#8217;s text can say \u201cREFRESH HIGH SCORES\u201d and be given a size of twenty. Once you&#8217;re finished, the user interface should look similar to the one seen in figure 7.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-90601\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/04\/graphical-user-interface-application-description-4.jpeg\" alt=\"The finished UI\" width=\"883\" height=\"383\" \/><\/p>\n<p><strong>Figure 7: The finished UI<\/strong><\/p>\n<p>While not required, if you wish to change the alignment and size of any other text, all you need to do is find the <em>Text <\/em>component in each object and adjust the size, alignment, and other properties to your liking. After that, all that&#8217;s left before returning to coding is making the scripts themselves. You will need just a single C# scripts, called <em>HighScoreControl<\/em>. Creating scripts is done by right-clicking in the <em>Assets <\/em>window and navigating to <em>Create-&gt;C# Script<\/em>. This script will be called <em>HighScoreControl<\/em>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-90602\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/04\/graphical-user-interface-application-description-5.jpeg\" alt=\"Creating a new C# script\" width=\"626\" height=\"750\" \/><\/p>\n<p><strong>Figure 8: Creating a new C# script<\/strong><\/p>\n<p>Once you have created your script, open it by double clicking the script in the <em>Assets <\/em>window.<\/p>\n<h2>Unity App \u2013 HighScoreControl script<\/h2>\n<p>The <em>HighScoreControl<\/em> script is responsible for both sending and retrieving data to and from the MySQL database. Of these two actions, getting the scores is likely the easiest, as it involves creating a <code>UniyWebRequest<\/code> to send an HTTP request. That&#8217;s the point in which the <em>display <\/em>PHP script from earlier comes in. The server script will be executed and send data back into Unity to later display in the UI created earlier. Posting a new score follows a similar pattern, but requires you use the POST method to send data to <em>addscore.php<\/em>. Before doing this, the user&#8217;s input is also hashed using the SHA256 algorithm as a basic security measure. In real-world applications, you would likely need to do more than just hash your values to secure them. But, for the purpose of this example, this process will be kept simple. Once the values are sent through the HTTP request, <code>addscore<\/code> will handle the process of adding the score to the database.<\/p>\n<p>For this script to function correctly, you&#8217;ll need the following using statements added at the top of your script:<\/p>\n<pre class=\"lang:c# theme:vs2012\">using System;\r\nusing System.Collections;\r\nusing System.Security.Cryptography;\r\nusing System.Text.RegularExpressions;\r\nusing UnityEngine;\r\nusing UnityEngine.Networking;\r\nusing UnityEngine.UI;<\/pre>\n<p>Within the <em>HighScoreControl <\/em>class itself, add these variables:<\/p>\n<pre class=\"lang:c# theme:vs2012\">private string secretKey = \"mySecretKey\";\r\npublic string addScoreURL = \r\n        \"http:\/\/localhost\/HighScoreGame\/addscore.php?\";\r\npublic string highscoreURL = \r\n         \"http:\/\/localhost\/HighScoreGame\/display.php\";\r\npublic Text nameTextInput;\r\npublic Text scoreTextInput;\r\npublic Text nameResultText;\r\npublic Text scoreResultText;<\/pre>\n<p>You may recognize the <code>secretyKey<\/code> value from the <em>addscore.php <\/em>script. Make sure that this value matches the version seen in <code>addscore<\/code> <strong>exactly<\/strong>. Additionally, the two URL strings will be used to point Unity to where the server scripts are so data can be sent and retrieved from the database using those PHP scripts. Finally, four <em>Text <\/em>objects are set up in code. These will be used to change the text seen in the UI. Later on, Unity will be told which objects in the editor are to be changed using these variables.<\/p>\n<p>Next come two methods, one for getting scores, the other for sending. These will be the methods tied to your buttons in the UI. Both methods start coroutines that will soon be defined, while quickly resetting some text to their defaults.<\/p>\n<pre class=\"lang:c# theme:vs2012\">public void GetScoreBtn()\r\n{\r\nnameResultText.text = \"Player: \\n \\n\";\r\nscoreResultText.text = \"Score: \\n \\n\";\r\nStartCoroutine(GetScores());\r\n}\r\npublic void SendScoreBtn()\r\n{\r\n  StartCoroutine(PostScores(nameTextInput.text, \r\n     Convert.ToInt32(scoreTextInput.text)));        \t\r\n  nameTextInput.gameObject.transform.parent.GetComponent&lt;InputField&gt;().text = \"\";\r\n  scoreTextInput.gameObject.transform.parent.GetComponent&lt;InputField&gt;().text = \"\";\r\n}<\/pre>\n<p>Speaking of coroutines, now would be a good time to go ahead and create the first one. The <code>GetScores<\/code> coroutine, as the name implies, will be responsible for communicating with the MySQL database in order to retrieve the top five scores along with player names currently stored in the database. As mentioned before, an HTTP request will be sent to communicate with the <em>display.php <\/em>script, which will then query the database. This PHP script will organize the data before Unity wetakes that data and separates the returned information to neatly fit it into the texts of <code>nameResultText<\/code> and <code>scoreResultText<\/code>. Those curious underscores found in the echo statements at the end of <em>display <\/em>will be used to more easily separate this data.<\/p>\n<pre class=\"lang:c# theme:vs2012\">IEnumerator GetScores()\r\n{\r\n\tUnityWebRequest hs_get = UnityWebRequest.Get(highscoreURL);\r\n\tyield return hs_get.SendWebRequest();\r\n\tif (hs_get.error != null)\r\n\t\tDebug.Log(\"There was an error getting the high score: \"\r\n                + hs_get.error);\r\n\telse\r\n\t{\r\n\t\tstring dataText = hs_get.downloadHandler.text;\r\n\t\tMatchCollection mc = Regex.Matches(dataText, @\"_\");\r\n\t\tif (mc.Count &gt; 0)\r\n\t\t{\r\n\t\t\tstring[] splitData = Regex.Split(dataText, @\"_\");\r\n\t\t\tfor (int i =0; i &lt; mc.Count; i++)\r\n\t\t\t{\r\n\t\t\t\tif (i % 2 == 0)\r\n\t\t\t\t\tnameResultText.text += \r\n                                        splitData[i];\r\n\t\t\t\telse\r\n\t\t\t\t\tscoreResultText.text += \r\n                                        splitData[i];\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}<\/pre>\n<p>Next comes <code>PostScores<\/code>, which will handle the process of putting new data into the database. It takes two parameters which correspond to the inputs in the UI input fields. It will first hash the input along with the secret key, then construct a POST URL to send the player&#8217;s name and score with alongside the newly created hash. Like with <code>GetScore<\/code>, another HTTP request is sent, this time calling upon <em>addscore.php <\/em>to enter the new data into the database. The PHP script handles the rest from there, comparing the hash it received with the one it creates using similar data before inserting the data.<\/p>\n<pre class=\"lang:c# theme:vs2012\">IEnumerator PostScores(string name, int score)\r\n{\r\n\tstring hash = HashInput(name + score + secretKey);\r\n\tstring post_url = addScoreURL + \"name=\" + \r\n           UnityWebRequest.EscapeURL(name) + \"&amp;score=\" \r\n           + score + \"&amp;hash=\" + hash;\r\n\tUnityWebRequest hs_post = UnityWebRequest.Post(post_url, hash);\r\n\tyield return hs_post.SendWebRequest();\r\n\tif (hs_post.error != null)\r\n\t\tDebug.Log(\"There was an error posting the high score: \" \r\n                + hs_post.error);\r\n}<\/pre>\n<p><code>PostScores<\/code> is still looking for the <code>HashInput<\/code> method at this point, so you&#8217;ll need to finish the script by adding this method. All it&#8217;s doing is taking a single input string, which is constructed using the player&#8217;s name, score, and your secret key, and constructing a hash based on that string using the SHA256 algorithm. It will then return this hash to <code>PostScores<\/code> to be sent in the HTTP request.<\/p>\n<pre class=\"lang:c# theme:vs2012 \">public string HashInput(string input)\r\n{\r\n\tSHA256Managed hm = new SHA256Managed();\r\n\tbyte[] hashValue = \t\r\n            hm.ComputeHash(System.Text.Encoding.ASCII.GetBytes(input));\r\n\tstring hash_convert = \r\n             BitConverter.ToString(hashValue).Replace(\"-\", \"\").ToLower();\r\n\treturn hash_convert;\r\n}<\/pre>\n<p>The <em>HighScoreControl <\/em>script is now complete. Be sure to save your work, then return to the Unity editor for a few final tasks.<\/p>\n<h2>Unity app \u2013 Finishing UI<\/h2>\n<p>Start by attaching the <em>HighScoreControl <\/em>script to the <em>Main Camera <\/em>object, as seen in figure 9.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-90603\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/04\/graphical-user-interface-description-automaticall-3.jpeg\" alt=\"Assigning HighScoreControl to Main Camera\" width=\"942\" height=\"757\" \/><\/p>\n<p><strong>Figure 9: Assigning <em>HighScoreControl <\/em>to <em>Main Camera<\/em><\/strong><\/p>\n<p>Make sure <em>Canvas <\/em>is expanded to show all the UI elements underneath it, then drag the <em>Text <\/em>objects of both <em>NameField <\/em>and <em>ScoreField <\/em>into <em>Name Text Input <\/em>and <em>Score Text Input, <\/em>respectively. Then bring <em>NameResults <\/em>to <em>Name Result Text<\/em>, and <em>ScoreResults <\/em>to <em>Score Result Text<\/em>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-90604\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/04\/a-picture-containing-graphical-user-interface-des.jpeg\" alt=\"Setting all HighScoreControl fields\" width=\"907\" height=\"783\" \/><\/p>\n<p><strong>Figure 10: Setting all <em>HighScoreControl <\/em>fields<\/strong><\/p>\n<p>Next, choose the <em>SendScoreButton <\/em>and assign it the <em>SendScoreBtn <\/em>method. To do this, navigate to the <em>Button <\/em>component in the <em>Inspector <\/em>window and find the <em>OnClick <\/em>event list. There, click the plus icon to add a new event.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-90605\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/04\/graphical-user-interface-text-application-descr.jpeg\" alt=\"Creating a new OnClick event\" width=\"591\" height=\"222\" \/><\/p>\n<p><strong>Figure 11: Creating a new <em>OnClick <\/em>event<\/strong><\/p>\n<p>Drag the <em>Main Camera <\/em>object into the object field. Why the <em>Main Camera <\/em>object in particular? Because it&#8217;s the object with the <em>HighScoreControl <\/em>script attached to it.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-90606\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/04\/graphical-user-interface-website-description-aut.jpeg\" alt=\"Assigning an object to get the function from\" width=\"913\" height=\"568\" \/><\/p>\n<p><strong>Figure 12: Assigning an object to get the function from<\/strong><\/p>\n<p>Click on the <em>No Function <\/em>drop down menu, and then navigate to <em>HighScoreControl-&gt;SendScoreBtn <\/em>to set the method for this button.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-90607\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/04\/graphical-user-interface-application-description-6.jpeg\" alt=\"Assigning the button function\" width=\"559\" height=\"506\" \/><\/p>\n<p><strong>Figure 13: Assigning the button function<\/strong><\/p>\n<p>Do the same for the <em>RefreshHighScoreButton <\/em>object, using the <em>GetScoreBtn <\/em>method instead. Once you&#8217;ve done that, try out the project using the play button at the top of the editor. Start by seeing if you can retrieve the current set of high scores. Then, try entering a score of your own, then refresh the top five to see the change.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-90608\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/04\/graphical-user-interface-application-description-7.jpeg\" alt=\"The completed app using MySQL with Unity\" width=\"890\" height=\"392\" \/><\/p>\n<p><strong>Figure 14: The completed app<\/strong><\/p>\n<h2>Using MySQL with Unity<\/h2>\n<p>A database can be easily made to store all kinds of data, whether it be interesting stats from various players or rankings. Now that you&#8217;ve been shown how to set up a basic database with a Unity app, you can expand this knowledge by experimenting with different database value types, multiple tables, and more. On the Unity side, you can try using data from a database to change a game in different ways. For instance, what if a player of higher rank meets one of a lower rank? What would you change within the game itself to reflect this scenario? While Unity is designed as a game engine, there&#8217;s also applications outside of video games that you can use it for that utilize these same database integration concepts. There&#8217;s much that can be done with this tech, some knowledge, and a little creativity.<\/p>\n<p><em>If you liked this article, you might also like\u00a0<\/em><a href=\"https:\/\/www.red-gate.com\/simple-talk\/dotnet\/c-programming\/saving-game-data-with-unity\/\"><em>Saving Game Data with Unity.<\/em><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Even games must store data like top scores. In this article, Lance Talbert explains how to save data using MySQL with Unity.&hellip;<\/p>\n","protected":false},"author":317499,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538,145792],"tags":[5134],"coauthors":[52549],"class_list":["post-90594","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","category-mysql","tag-sql-prompt"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/90594","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/317499"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=90594"}],"version-history":[{"count":5,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/90594\/revisions"}],"predecessor-version":[{"id":90610,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/90594\/revisions\/90610"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=90594"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=90594"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=90594"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=90594"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}