Game Engine/Unity (유니티)

Unity에서 MySQL 사용하기 (Windows) - 2

은연일체 2021. 11. 17. 15:14

이전 글에서 PHP와 MySQL을 연동하는 작업을 했다.

이번에는 이전 글에 이어서 Unity에서 PHP를 사용하여 MySQL에 연동하는 작업을 해볼 것이다.

 

 

Unity에서 MySQL 사용하기 (Windows) - 1

Unity에서 데이터베이스를 사용하기 위해 여러 가지 시도를 해봤지만 DLL 파일의 여러 가지 문제로 시행착오를 많이 겪었다. 수많은 시행착오 끝에 PHP를 통해 MySQL과 Unity를 연동하는 것에 성공했

foreverhappiness.tistory.com

 

 

Unity에서 phpMyAdmin을 통해 MySQL 사용하기

데이터베이스 만들기

 

phpMyAdmin에 돌어가서 데이터베이스를 클릭한다.

 

 

만들기를 눌러 데이터베이스를 생성한다.

테스트를 위해 나는 highscores라는 이름으로 만들었다.

 

 

SQL탭으로 이동해서 쿼리를 실행시켜 테이블을 생성한다.

이때 데이터베이스가 정상적으로 선택되었는지 잘 확인하자.

아래와 같은 쿼리를 입력하고 실행을 누른다.

복사 붙여넣기가 되지 않기 때문에 직접 입력해야 한다.

 

CREATE TABLE scores (
   name VARCHAR(15) NOT NULL DEFAULT 'anonymous',
   score INT(10) UNSIGNED NOT NULL DEFAULT 0
)
ENGINE=MyISAM

 

 

정상적으로 실행이 되었다면 아래와 같은 결과가 나온다.

 

 

테스트 데이터를 넣어주기 위해 아래 쿼리도 함께 실행해준다.

INSERT INTO scores (name, score) VALUES ('John', 100), 
('Sally', 110), ('Phil', 90), ('Katy', 130), ('Jack', 150)

 

보기에서 다음과 같이 확인할 수 있다.

 

 

 

서버 스크립트 생성

 

서버와 유니티의 소통을 위해 PHP 스크립트가 필요하다.

서버에 저장할 PHP 스크립트들을 담기 위해 C:\Apache24\htdocs 에 HighScoreGame이라는 폴더를 만들어주었다.

 

 

PHP 파일을 만들 때는 메모장을 사용해도 되지만 나는 Notepad++를 사용하고 있다.

별도의 설치가 필요하지만 공식 홈페이지에서 간단하게 설치할 수 있기 때문에 필요하다면 아래 링크에서 다운로드하도록 하자.

 

Downloads | Notepad++

 

notepad-plus-plus.org

 

아래 두 개의 php 파일을 만들어 C:\Apache24\htdocs\HighScoreGame 에 저장한다.

 

display.php

1~4번째 줄의 hostname, username, password, database를 잘 확인하고 저장한다.

스크립트에 대해 간단히 설명하자면 DB 연결 후 점수가 높은 상위 5명의 정보를 가져오는 스크립트이다.

<?php
$hostname = 'localhost';
$username = 'root';
$password = '';
$database = 'highscores';
 
try 
{
	$dbh = new PDO('mysql:host='. $hostname .';dbname='. $database, 
         $username, $password);
} 
catch(PDOException $e) 
{
	echo '<h1>An error has occurred.</h1><pre>', $e->getMessage()
            ,'</pre>';
}
 
$sth = $dbh->query('SELECT * FROM scores ORDER BY score DESC LIMIT 5');
$sth->setFetchMode(PDO::FETCH_ASSOC);
 
$result = $sth->fetchAll();
 
if (count($result) > 0) 
{
	foreach($result as $r) 
	{
		echo $r['name'], "\n _";
		echo $r['score'], "\n _";
	}
}

 

addscore.php

마찬가지로 1~5번째 줄의 변수를 조정해준다.

이때 secretKey는 Unity와 MySQL사이에 데이터를 주고받을 때 암호화하는 해시값으로 사용된다.

나중에 Unity에서도 사용하기 때문에 이 secretKey는 꼭 기억해두도록 하자.

<?php
$hostname = 'localhost';
$username = 'root';
$password = '';
$database = 'highscores';
$secretKey = "mySecretKey";
 
try 
{
	$dbh = new PDO('mysql:host='. $hostname .';dbname='. $database, 
           $username, $password);
} 
catch(PDOException $e) 
{
	echo '<h1>An error has ocurred.</h1><pre>', $e->getMessage() 
            ,'</pre>';
}
 
$hash = $_GET['hash'];
$realHash = hash('sha256', $_GET['name'] . $_GET['score'] . $secretKey);
	
if($realHash == $hash) 
{ 
	$sth = $dbh->prepare('INSERT INTO scores VALUES (null, :name
            , :score)');
	try 
	{
		$sth->bindParam(':name', $_GET['name'], 
                  PDO::PARAM_STR);
		$sth->bindParam(':score', $_GET['score'], 
                  PDO::PARAM_INT);
		$sth->execute();
	}
	catch(Exception $e) 
	{
		echo '<h1>An error has ocurred.</h1><pre>', 
                 $e->getMessage() ,'</pre>';
	}
}

 

 

 

 

Unity와 MySQL 연동

 

유니티 다운로드가 안돼있다면 아래 링크를 참고하자

 

Unity 다운로드

요즘 디지털 트윈, 메타버스와 같은 기술들이 유행하면서 Unity와 같은 엔진들이 단순히 게임 엔진의 역할만 하는 것이 아니라 가상현실, 가상공간을 구현하는 도구로도 많이 사용되고 있다. 나

foreverhappiness.tistory.com

 

유니티 허브를 열어 새 프로젝트를 만들어보자

 

 

3D 템플릿을 선택하고 프로젝트 이름은 HighScore로, 위치는 편한 경로로 해도 무방하다.

 

 

프로젝트가 생성되면 UI 오브젝트를 여러 개 생성할 것이다.

아래와 같이 Text, Button, Input Field 세 가지만 사용할 건데 표를 보고 오브젝트들을 차례대로 만들어보자.

 

Name Object Type Pos X Pos Y Width Height
NameResults Text -365 50 162 297
ScoreResults Text -202 50 162 297
NameField Input Field 245 58 160 30
ScoreField Input Field 245 -36 160 30
NameFieldLabel Text 108 58 103 30
ScoreFieldLabel Text 108 -35 103 30
InputDirections Text 246 148 274 51
SendScoreButton Button 240 -130 170 65
RefreshHighScoreButton Button -287 -130 170 65

 

모든 오브젝트를 생성하고 텍스트를 조금 변경하면 아래와 같은 화면을 만들 수 있다.

 

 

Assets에서 오른쪽 클릭 후 Create > C# Script를 눌러 HighScoreControl이라는 스크립트 파일을 생성한다.

 

 

C# 스크립트에 아래와 같이 입력한다.

secretKey에는 아까 addscore.php에서 입력해줬던 값을 입력해준다.

 

HighScoreControl.cs

using System;
using System.Collections;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class HighScoreControl : MonoBehaviour
{
    private string secretKey = "mySecretKey";
    public string addScoreURL = "http://localhost/HighScoreGame/addscore.php?";
    public string highscoreURL = "http://localhost/HighScoreGame/display.php";
    public Text nameTextInput;
    public Text scoreTextInput;
    public Text nameResultText;
    public Text scoreResultText;

    public void GetScoreBtn()
    {
        nameResultText.text = "Player: \n \n";
        scoreResultText.text = "Score: \n \n";
        StartCoroutine(GetScores());
    }
    public void SendScoreBtn()
    {
        StartCoroutine(PostScores(nameTextInput.text,
           Convert.ToInt32(scoreTextInput.text)));
        nameTextInput.gameObject.transform.parent.GetComponent<InputField>().text = "";
        scoreTextInput.gameObject.transform.parent.GetComponent<InputField>().text = "";
    }

    IEnumerator GetScores()
    {
        UnityWebRequest hs_get = UnityWebRequest.Get(highscoreURL);
        yield return hs_get.SendWebRequest();
        if (hs_get.error != null)
            Debug.Log("There was an error getting the high score: "
                    + hs_get.error);
        else
        {
            string dataText = hs_get.downloadHandler.text;
            MatchCollection mc = Regex.Matches(dataText, @"_");
            if (mc.Count > 0)
            {
                string[] splitData = Regex.Split(dataText, @"_");
                for (int i = 0; i < mc.Count; i++)
                {
                    if (i % 2 == 0)
                        nameResultText.text +=
                                            splitData[i];
                    else
                        scoreResultText.text +=
                                            splitData[i];
                }
            }
        }
    }

    IEnumerator PostScores(string name, int score)
    {
        string hash = HashInput(name + score + secretKey);
        string post_url = addScoreURL + "name=" +
               UnityWebRequest.EscapeURL(name) + "&score="
               + score + "&hash=" + hash;
        UnityWebRequest hs_post = UnityWebRequest.Post(post_url, hash);
        yield return hs_post.SendWebRequest();
        if (hs_post.error != null)
            Debug.Log("There was an error posting the high score: "
                    + hs_post.error);
    }

    public string HashInput(string input)
    {
        SHA256Managed hm = new SHA256Managed();
        byte[] hashValue =
                hm.ComputeHash(System.Text.Encoding.ASCII.GetBytes(input));
        string hash_convert =
                 BitConverter.ToString(hashValue).Replace("-", "").ToLower();
        return hash_convert;
    }
}

 

좌측 Hierarchy에서 Main Camera를 선택하고 스크립트를 Inspector의 맨 아래쪽에 끌어다 놓는다.

 

 

아래와 같이 오브젝트들을 끌어다 놓는다.

 

 

버튼 이벤트를 추가해주기 위해 Hierarchy에서 SendScoreButton을 선택하고 Inspector의 On Click()을 찾아 + 버튼을 누른다.

 

 

아래와 같이 Main Camera를 끌어다 놓는다.

 

 

Function에는 HighScoreControl > SendScoreBtn을 찾아 넣는다.

 

 

RefreshHighScoreButton에도 동일하게 function을 GetScoreBtn으로 설정한다.

 

 

이제 Play 버튼을 눌러 REFRESH HIGH SCORES 버튼을 클릭해보면 아래와 같이 결과가 잘 나오는 것을 확인할 수 있다. (무슨 일인지 SEND SCORE 버튼은 잘 적용되지 않는다. 추후 수정 예정)

 

 

 

WebGL로도 성공이 되는 걸 확인했지만 무슨 일인지 갑자기 WebGL로는 결과가 나오질 않는다.. (원인 파악 중)

 

 

 

참고 자료

MySQL과 phpMyAdmin 연동

 

 

윈도우 10 Server 만들기 아파치, PHP, MySQL, PhpMyAdmin 설치

윈도우 10 Server 만들기 아파치, PHP, MySQL, PhpMyAdmin 그동안 '아파치', 'PHP', 'MYSQL' , 'PhpMyAdmin' 등을 리눅스에 설치해서 서버 환경을 만들고 공부를 했었는데 문뜩 [윈도우]에도 이런 환경을 만들어..

abc0123.tistory.com

Unity에서 PHP를 통해 MySQL과 연동

 

Using MySQL with Unity - Simple Talk

Even games must store data like top scores. In this article, Lance Talbert explains how to save data using MySQL with Unity.

www.red-gate.com