한달 반 전쯤에 공부해봤던 코드인데 올리는 걸 깜빡했다.
php 서버와 mysql 을 이용하여 unity 클라이언트에서 로그인하는 코드를 짜보았다.
보통 모바일 게임에서는
구글 / 네이버 등의 외부 계정을 통한 로그인과
게임에 직접 계정을 생성하는 방법 (그런데 로그인 단계를 간소화하려는 것인지 최근엔 많이 안 쓰이는 것 같다.)
기기 내에 계정 정보를 생성하여 별로 가입 없이 자동으로 계정을 생성하는 게스트 로그인 방식이 있다.
여기서는 게스트 로그인 방식을 구현해보았다.
맨 처음 앱을 실행하였을 때에는 계정이 없는 상태이기 때문에 새로 생성해야 하며
이후 다시 실행했을 때에는 이미 생성된 계정이 있으므로 그 계정을 통해 로그인을 시도한다.
일단 서버에 데이터를 요청할 때 사용되는 ConnectManager.cs 클래스를 생성하였다.
구글링을 이용하여 찾은 코드를 현재 버전에 맞게 약간 수정하였다.
어디서든 접근 가능하도록 singleton 패턴을 이용하였다.
서버와 통신할 때에는 SendData 메소드를 이용하며
매개변수로 url주소 / POST방식으로 전송할 데이터 / 송신받은 후 실행될 메소드를 전달한다.
서버로 데이터를 요청하고 나면, 곧 서버가 보내준 데이터를 수신하게 되는데,
불필요한 헤더 정보를 제외하고 필요한 데이터만 골라내는 것이 SetSessionCookie 메소드이다.
골라낸 데이터는 result 변수에 저장되고,
다른 클래스에서 이 result 변수를 참조하여 결과를 확인할 수 있다.
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 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | using UnityEngine; using System.Collections; using System.Collections.Generic; public delegate void resultFunction(); public class ConnectManager { private static ConnectManager inst; public static ConnectManager getInst() { if (inst == null) { inst = new ConnectManager(); inst.InitSetting(); } return inst; } private Dictionary<string, string> hsHeader; private string result; public string _result { get { return result; } } public void InitSetting() { hsHeader = new Dictionary<string, string>(); } public IEnumerator SendData(string url, WWWForm form, resultFunction resultFunction) { WWW www; if (this.hsHeader.Count > 0) { www = new WWW(url, form.data, hsHeader); } else { www = new WWW(url, form.data); } yield return www; SetSessionCookie(www); result = www.text; www.Dispose(); resultFunction(); } private void SetSessionCookie(WWW www) { Dictionary<string, string> headers = www.responseHeaders; foreach (KeyValuePair<string, string> kvPair in headers) { if (kvPair.Key.ToLower().Equals("set-cookie")) { string stHeader = ""; string stJoint = ""; string[] astCookie = kvPair.Value.Split( new string[] { ";" }, System.StringSplitOptions.None); foreach (string stCookie in astCookie) { if (!stCookie.Substring(0, 5).Equals("path =")) { stHeader += stJoint + stCookie; stJoint = ";"; } } if (stHeader.Length > 0) { this.hsHeader["Cookie"] = stHeader; } else { this.hsHeader.Clear(); } } } } } | cs |
로그인 Scene에서는 아래와 같이 UI를 생성해주고
(텍스트 박스는 닉네임을 입력하는 공간이다.)
![](https://t1.daumcdn.net/cfile/tistory/234C4E4D57C25EA028)
GameManager라는 빈 오브젝트에는 phplogin.cs 라는 스크립트 파일을 작성하여 컴포넌트로 넣어주었다.
createAccount 와 nameField 변수에는 방금 전에 생성한 텍스트박스UI와 버튼UI를 연결해준다.
앱이 실행되면 PlayerPrefs 로 저장된 계정 정보가 있는지 판단하고,
없으면 계정생성 / 있으면 곧바로 로그인을 시도 한다.
계정 생성을 할 땐 입력받은 닉네임을 송신할 데이터에 포함시키고
서버로부터 전송된 고유한 계정아이디를 PlayerPrefs 에 저장한다. 그리고 로그인.
로그인할 땐 보유한 아이디를 서버로 전송하여 로그인한다.
(아래 코드에서는 로그인 검증하는 부분이 빠져있는데, 서버쪽에서 날리는 에러 결과인지 판단하면 된다.)
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 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | using UnityEngine; using UnityEngine.UI; using System.Collections; using System.Collections.Generic; using System.Text; using System.IO; using System.Net; using System; using UnityEngine.SceneManagement; public class phplogin : MonoBehaviour { public GameObject createAccount; public InputField nameField; // Use this for initialization void Start() { if (!CheckExistAccount()) { createAccount.SetActive(true); } else { Login(); } } bool CheckExistAccount() { if (PlayerPrefs.HasKey("AccountCode")) return true; else return false; } public void CreateAccount() { WWWForm form = new WWWForm(); form.AddField("name", nameField.text); resultFunction rf = new resultFunction(SaveAccountData); StartCoroutine(ConnectManager.getInst().SendData("########createAccount.php", form, rf)); } public void SaveAccountData() { string accountCode = ConnectManager.getInst()._result; PlayerPrefs.SetString("AccountCode", accountCode); Debug.Log(accountCode); Login(); } public void Login() { Debug.Log("로그인 합니다."); string id = PlayerPrefs.GetString("AccountCode"); WWWForm form = new WWWForm(); form.AddField("id", id); resultFunction rf = new resultFunction(LoginResult); StartCoroutine(ConnectManager.getInst().SendData("#########Login.php", form, rf)); } public void LoginResult() { Debug.Log(ConnectManager.getInst()._result); SceneManager.LoadScene("MainScene"); } } | cs |
서버 쪽에 login.php 와 createAccount.php 를 작성한다.
임시용으로 에러 처리 결과는 'no result' 로 했고, 로그인 성공시의 결과도 그냥 id를 재전송하는 것으로 했는데
추후에 헤더를 작성하여 그 구조에 맞게 전송하는 것으로 처리하면 될 것 같다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?php require('conf.php'); session_start(); $id = $_POST["id"]; $query_search = "select * from user where id = '" . $id . "'"; $query_exec = mysqli_query($dbServer, $query_search) or die(mysql_error("DB error")); $rows = mysqli_fetch_assoc($query_exec); if($rows) { $_SESSION['id'] = $_POST['id']; echo $_SESSION['id']; } else { echo "no result"; } ?> | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?php require('conf.php'); function createAccount($id, $name){ $sql = "INSERT INTO user (id, name) VALUES ('" . $id . "', '" . $name . "')"; $query_exec = mysqli_query($dbServer, $sql); } session_start(); $id = uniqid(); $name = $_POST['name']; createAccount($id, $name); $_SESSION['id'] = $id; echo $id; ?> | cs |
댓글