본문 바로가기

유니티 개발 정보/강좌

유니티와 페이스북 연동하기 (2/3)

원문 보기 
1편 튜토리얼 보기
(역자 주 : 본 튜토리얼에서 예제를 따라하기위해 php, mysql, PHPMyAdmin등 여러 설치할 것들이 있습니다. 그래서 이를 
처음으로 접하시는 분들에게는 중간중간 어려움을 겪을 수도 있지만, 이번 기회에 설치법과 간단한 사용법을 익힐 수 있는 좋은 예제라고 생각되니 한번 해보시면 많은 도움이 될 것입니다.)


시작하기 전에 알아야할 것:  이 글은 유니티에서 페이스북을 연동시키는 튜토리얼이다. 이는 자신의 웹-앱에 페이스북을 연결하고 싶어하는 유니티 개발자를 위한 기술 가이드이다. 만약 이 주제가 흥미롭게 들린다면, 주저없이 한번 읽어 보자.

두번째 튜토리얼에서 배울 내용은 다음과 같다:

  • 점수를 보내고 저장하는 방법
  • 점수를 받아오는 방법
  • 점수와 페이스북 프로필 사진을 출력하는 방법
전 튜토리얼을 하지 않았다면, 반드시 파트 1 튜토리얼을 읽어야 한다.

게임 만들기

점수를 얻기위해서 게임을 만들어야 한다. 시연을 위해, 이번 강좌에서 매우 간단한 게임을 만들 것이다. 하지만 여기서 배웠던 것들을 당신의 게임에 맞게 사용해야 한다. 우리는 주사위 굴리기 게임을 만들 것인데 유저는 무작위 숫자를 굴리기 위해 버튼을 눌러야 한다.

새로운 프로젝트를 만들고 다음 스크립트를 추가하자:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class DiceGame : MonoBehaviour
{
    public static string FacebookId = "1"//We'll link up with FacebookManager later.
    private const int max = 6; //Max score, the sides on the dice
    private string btnText = "Press to roll";
    void OnGUI()
    {
        if (GUI.Button(new Rect(10, 10, 200, 50), btnText))
        {
            int score = UnityEngine.Random.Range(1, max + 1); //Calculate our score.
            btnText = string.Format("You rolled {0}, \nclick to try again.", score);
 
            StartCoroutine(submitHighscore(score, FacebookId));
        }
 
    }
 
    IEnumerator submitHighscore(int score, string fbid)
    {
        yield return null//We'll implement this later.
    }
}

어려운 건 없다. 단지, 무작위 숫자를 생성하는 버튼을 누르면, submitHighsocre 코루틴을 시작한다. 이 함수는 점수를 넣기 위해서 웹 요청을 해야하는데 일단 웹서비스를 만들어 보자!

웹서비스 만들기

점수를 저장하기 위해서, 데이터베이스를 가진 웹서비스가 필요하다. 다행히 우리는 이미 로컬상에 동작하는 웹서비스를 가지고 있어서, 이를 이용해 테스트할 수 있다. 간단한 데이터베이스를 만들어 보자.



페이스 북 id, 점수 그리고 만들어진 날짜까지 저장할 것이다. PHPMyadmin을 이용해서 "highscore"라는 이름으로 데이터베이스를 만들자:
데이터 베이스를 만들기 위해서는 다음과 같은 SQL을 실행해야 한다.
(역자 주 : PHPMyadmin은 웹상에서 MySQLDB를 관리할 수 있게 도와주는 오픈 소스 도구입니다.
이를 실행하기 위해서는 서버에 MySQL에 PHP가 설치되어 있어야 합니다 . 자세한 설명은 관련 블로그 링크로 대신하겠습니다. Apache & PHP & MySql설치PHPMyadmin설치)

1
2
3
4
5
6
CREATE TABLE `highscores`.`scores` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`fbid` TEXT NOT NULL ,
`score` INT NOT NULL ,
`creation_date` TIMESTAMP NOT NULL
) ENGINE = INNODB;

이제 우리는 데이터 베이스 설정을 했고, 점수를 넣는 스크립트를 만들어 보자. 새롭게 "insert_highscore.php"라는 이름의 파일을 만들어
www 디렉토리에 넣어보자
(역자 주 : www 디렉토리는 apache 서버일경우 htdocs폴더를 의미합니다.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
 
    mysql_connect('localhost','root',''); //Connect to the databsae
    mysql_select_db('highscores');
 
    $score = @$_GET['score'];
    $fbid = @$_GET['fbid'];
 
    if(!$score || !$fbid//Ensure both parameters are passed
        die("No fbid or score");
 
    mysql_query("INSERT INTO scores (fbid, score) VALUES ('$fbid', $score)"); //Execute the query
    
?>

첫 두번째 라인은 데이터베이스에 연결을 해서 적절한 데이터베이스를 선택한다. 다음, 입력을 검사해서 score와 fbid가 제공되지 않으면, 실행을 멈춘다. 확인을 한 후에, 이 값들을 SQL을 사용하여 데이터베이스에 넣을 것이다. 좋다, 이제 http://localhost/insert_highscore.php?fbid=4&score=1로 방문해보자. phpMyAdmin을 이용해서 highscore 데이터베이스에있는 score 테이블에 새로운 행이 생겼는지 확인해라.



이제 데이터를 삽입하는 것은 가능하다. 다음으로 데이터를 받는 방법에 대해서 알아보자. "get_highscores.php"라는 이름의 새로운 페이지를 만들어보자. 우리는 유저의 모든 점수를 원하지 않는다. 단지 가장 높은 점수 하나만 있으면 된다. GROUP BY를 사용해서 간단하게 구현할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
 
    mysql_connect('localhost','root','');
    mysql_select_db('highscores');
 
    $scoresQuery = mysql_query("SELECT
                                    MAX(score) as max_score,
                                    fbid
                                FROM
                                    scores
                                GROUP BY
                                    fbid
                                ORDER BY
                                    max_score DESC");
 
    while($scoresRow = mysql_fetch_assoc($scoresQuery))
        echo $scoresRow['fbid'] . ',' . $scoresRow['max_score'] . "<br />\n";
 
?>
또 다시 데이터베이스에 연결해서, 쿼리를 실행한다. 각 행에 대한 결과는 다음과 같다:

fbid,score
fbid,score
etc..

http://localhost/get_highscores.php를 실행해서 확인해보자. 만약 더 많은 점수가 필요하다면 insert_highscore.php를 다시 사용하면 된다.

다른 facebook id를 추가하면, get_highscores를 사용했을때 더 많은 행들을 볼 수 있을 것이다.

데이터 삽입하기

이제 우리는 웹서비스할 준비가 되었다. 이를 유니티 게임안에서 호출할 수 있게 해보자.
DiceGame 스크립트에 다음 소스를 추가해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
private Dictionary<stringint> scores; //The key is the facebook id, value is his score.
 
void Start()
{
    scores = new Dictionary<stringint>();
    StartCoroutine(retrieveHighscores()); //Start out by getting the current scores.
}
 
IEnumerator submitHighscore(int score, string fbid)
{
    WWW webRequest = new WWW("http://localhost/insert_highscore.php?score=" + score + "&fbid=" + fbid);
    yield return webRequest;
 
    yield return StartCoroutine(retrieveHighscores()); //After we submit we'd want an update, perhaps someone else played too!
}
 
IEnumerator retrieveHighscores()
{
    WWW webRequest = new WWW("http://localhost/get_highscores.php");
    yield return webRequest;
 
    string[] lines = webRequest.text.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); //Split the response by newlines.
 
    scores = new Dictionary<stringint>(); //Always reset our scores, as we just got new ones.
    foreach (string line in lines) //Parse every line
    {
        string[] parts = line.Split(',');
 
        string id = parts[0];
        int score = int.Parse(parts[1]);
 
        scores.Add(id,score);
    }
}

좋다, 우리는 유니티 내장된 WWW클래스와 적절한 GET 매개변수를 이용해서 웹페이지를 호출할 것이다. highscores를 웹으로 보낼 때마다, 자동적으로 새로운 highscores 값들을 받을 것이다. retrieveHighscores함수안에 파싱을 하는 부분이 다시 나오는데, 받은 highscores들의 값을 매 행으로 구분한 다음, ','(콤마)로 다시 구분할 것이다.

이 스크립트를 씬에 있는 게임 오브젝트에 넣어, 유니티 에디터안에서 실행을 해보자. 버튼을 누르면, 약간의 시간이 지나고 나서 적절하게 작동하는 것을 볼 수 있을 것이다. 데이터베이스에 새로운 행이 추가 되었는지 확인을 해보자.

페이스북에 연결하기

이제, 게임은 점수를 저장하고 받아올 수 있다. 그러나 아직 페이스북에는 연결되지 않았다. 

이제 ID를 받아오기 위해 FacebookManager 스크립트를 만들자:

1
2
3
4
5
6
7
8
9
10
11
public class FacebookManager : MonoBehaviour
{
    void Start()
    {
        Application.ExternalCall("GetCurrentUser");
    }
    public void GetCurrentUserComplete(string fbid)
    {
        DiceGame.FacebookId = fbid;
    }
}

"FacebookManager"라는 게임 오브젝트를 만들어 FacebookManager스크립트를 붙이고 웹으로 빌드를 하자. 
빌드를 한 xxxxx.html을 Facebook SDK를 구현하기위해 다음과 같이 바꾸자:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<script src="http://connect.facebook.net/en_US/all.js"></script>
<script type="text/javascript" src="http://webplayer.unity3d.com/download_webplayer-3.x/3.0/uo/UnityObject.js"></script>
<div id="fb-root"></div>
 
<script type='text/javascript'>
 
    //Fired when the facebook sdk has loaded
    window.fbAsyncInit = function()
    {
        FB.init(
        {
          appId      : '171298766297727',
          status     : true, // check login status
          cookie     : true, // enable cookies to allow the server to access the session
          oauth      : true, // enable OAuth 2.0
          xfbml      : false // dont parse XFBML
        });
 
        //Get the current login status.
        FB.getLoginStatus(function(loginStatusResponse)
        {
            if(!loginStatusResponse.authResponse) //Not logged in, log him in
                FB.login();
        });
 
    };
 
    function GetCurrentUser() //When we are logged in this shows our name.
    {
        FB.api('/me'function(meResponse)  //Do a graph request to /me
        {
            getUnity().SendMessage("FacebookManager"//Game object name, make sure this exists!
                                    "GetCurrentUserComplete"//Method to call
                                    meResponse.id); //Our serialized facebook data
        });
    }
 
    //Load the Facebook JS SDK
    (function(d){
     var js, id = 'facebook-jssdk'if (d.getElementById(id)) {return;}
     js = d.createElement('script'); js.id = id; js.async = true;
     js.src = "//connect.facebook.net/en_US/all.js";
     d.getElementsByTagName('head')[0].appendChild(js);
    }(document));
 
    function getUnity()
    {
        if (typeof unityObject != "undefined")
        {
            return unityObject.getObjectById("unityPlayer");
        }
        return null;
    }
    if (typeof unityObject != "undefined")
    {
        unityObject.embedUnity("unityPlayer""WebPlayer.unity3d", 960, 640);
    }
</script>
 
<div id='unityPlayer'></div>

페이지를 열고, 여러번 버튼을 눌러보자. 그리고 데이터베이스에가면 당신의 Facebook ID가 삽입된 것을 볼 수있을 것이다.

다음으로는 저장된 페이스북 ID를 가지고, 당신의 프로필 이미지를 보이게 할 것이다. Facebook Graph API을 통해서, 다음의 URL로 유저의 이미지를 얻을 수 있다.
http://graph.facebook.com/UID/picture/

DiceGame스크립트에서, retrieveHighscores를 다음과 같이 변경해보자:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private Dictionary<string, Texture2D> fbProfileImages = new Dictionary<string, Texture2D>();
   
    IEnumerator retrieveHighscores()
    {
        WWW webRequest = new WWW("http://localhost/get_highscores.php");
        yield return webRequest;
 
        string[] lines = webRequest.text.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
 
        scores = new Dictionary<stringint>(); //Always reset our scores, as we just got new ones.
        foreach (string line in lines)
        {
            string[] parts = line.Split(',');
 
            string id = parts[0];
            int score = int.Parse(parts[1]);
 
            if (!fbProfileImages.ContainsKey(id)) //Have we already loaded this user before?
            {
                //No, better get our image!
                WWW imageRequest = new WWW("http://graph.facebook.com/" + id + "/picture");
                yield return imageRequest;
                fbProfileImages.Add(id, imageRequest.texture);
            }
 
            scores.Add(id,score);
        }
    }


OnGUI는 다음과 같이 변경하자:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void OnGUI()
 {
     if (GUI.Button(new Rect(10, 10, 200, 50), btnText))
     {
         int score = UnityEngine.Random.Range(1, max + 1);
         btnText = string.Format("You rolled {0}, \nclick to try again.", score);
 
         StartCoroutine(submitHighscore(score, FacebookId));
     }
 
     float h = 10;
     foreach (var score in scores)
     {
         GUI.Label(new Rect(300, h, 200, 50), score.Value.ToString());
 
         if (fbProfileImages != null && fbProfileImages.ContainsKey(score.Key))
             GUI.DrawTexture(new Rect(230, h, 50, 50), fbProfileImages[score.Key]);
 
         h += 60;
     }
 }


fbProfileImages dictionary는 프로필 텍스쳐를 가지고 있는데, 새로운 유저가 발견될 때 마다, 새롭게 로드될 것이
다. 빌드를 하고 프로젝트를 다시 실행시켜 보자. 페이스북에서 프로필 사진을 가져오는 것이 이렇게 쉬울줄은 몰
랐을 것이다 :)



결과는 훌륭하지만, 여기 약간 수상한 부분이 있다. 마크 주커버그가 주사위 굴리기에서 7의 값을 가지고 있다!
다음 튜토리얼에서는 어떻게 이런 결과가 나오는지 찾아낼 것이고, 악의적인 유저들에의한 공격를 방어하는 방법을 배울 것이다.