공부/인프런 - 고박사

[뒤끝 강의] 온라인 게임 개발 #02 - 유저 관리 기능을 이용한 로그인

셩잇님 2023. 12. 4. 17:18
반응형

 

 

뒤끝

 

 이번 시간에는 '게임 유저 관리' 기능을 이용한 로그인을 배웁니다. 다만 학습하기 전 뒤끝에서 제공하는 함수는 크게 동기, 비동기, SendQueue로 호출할 수 있습니다. 각각에 대해서 먼저 알아보도록 하겠습니다. 🧐

 

동기

 

비동기

 

SendQueue

 

 


 

비동기 호출을 위한 처리

 

BackendManager 스크립트를 다음과 같이 수정합니다.

using UnityEngine;
using BackEnd;  // 뒤끝 SDK

public class BackendManager : MonoBehaviour
{
    private void Awake()
    {
        // Update() 메소드의 Backend.AsyncPoll() 호출을 위해 오브젝트 파괴 방지
        DontDestroyOnLoad(gameObject);

        // 뒤끝 서버 초기화
        BackendSetup();
    }

    private void Update()
    {
        // 서버의 비동기 메소드 호출(콜백 함수 풀링)을 위해 적성
        if (Backend.IsInitialized)
        {
            Backend.AsyncPoll();
        }
    }

    private void BackendSetup()
    {
        // 뒤끝 초기화
        var bro = Backend.Initialize(true);

        // 뒤끝 초기화에 대한 응답값
        if (bro.IsSuccess())
        {
            // 초기화 성공 시 statusCode 204 Success
            Debug.Log($"초기화 성공 : {bro}");
        }
        else
        {
            // 초기화 실패 시 statusCode 400대 에러 발생
            Debug.Log($"초기화 실패 : {bro}");
        }
    }
}

 

 이 후 새로운 신인 'Login' 신을 새롭게 만들어 주고, Build Setting에서 Login 씬과 Logo씬을 넣어줍니다. 이 후 씬 전환과 같은 유틸 메소드를 정의하는 Utils 스크립트를 새롭게 생성합니다.

 

Utils

using UnityEngine;
using UnityEngine.SceneManagement;

public enum SceneName
{
    Logo = 0,
    Login,
}

public class Utils
{
    public static string GetActiveScene()
    {
        return SceneManager.GetActiveScene().name;
    }

    public static void LoadScene(string sceneName = "")
    {
        if (sceneName == "")
        {
            SceneManager.LoadScene(GetActiveScene());
        }
        else
        {
            SceneManager.LoadScene(sceneName);
        }
    }

    public static void LoadScene(SceneName sceneName)
    {
        // SceneNames 열거형으로 받은 경우, ToString() 처리를 진행한다.
        SceneManager.LoadScene(sceneName.ToString());
    }
}

 

Utils 함수를 만들었으므로 LogoScenario 스크립트를 아래와 같이 수정해줍니다.

using UnityEngine;

public class LogoScenario : MonoBehaviour
{
    [SerializeField] private Progress progress;
    [SerializeField] private SceneName nextScene; // 추가 ⭕

    private void Awake()
    {
        SystemSetup();
    }

    private void SystemSetup()
    {
        // 활성화되지 않은 상태에서도 게임이 계속 진행
        Application.runInBackground = true;

        // 해상도 설정 (9:18.5, 1440x2960)
        int width = Screen.width;
        int height = (int)(Screen.width * 18.5f / 9);
        Screen.SetResolution(width, height, true);

        // 화면이 꺼지지 않도록 설정
        Screen.sleepTimeout = SleepTimeout.NeverSleep;

        // 로딩 애니메이션 시작, 재생 완료시 OnAfterProgress 실행
        progress.Play(OnAfterProgress);
    }

    private void OnAfterProgress()
    {
        Utils.LoadScene(nextScene); // 추가 ⭕
    }
}

 

 이 후 유니티에서 LogoScenario 컴포넌트의 NextScene 변수를 Login으로 설정하여 줍니다.

 


 

게임 유저 관리 - 로그인

 

유니티 UI 상에서 Login 패널을 만드는 장면은 모두 작성하지 않았습니다. 해당 내용은 고박사님의 영상에 아주 자세하게 설명해주시므로 영상을 참고하길 바랍니다.

 

LoginBase.cs

using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class LoginBase : MonoBehaviour
{
    [SerializeField] private TextMeshProUGUI textMessage;

    /// <summary>
    /// 메시지 내용, InputField 색상 초기화
    /// </summary>
    protected void ResetUI(params Image[] images)
    {
        textMessage.text = string.Empty;

        for (int i = 0; i < images.Length; i++)
        {
            images[i].color = Color.white;
        }
    }

    /// <summary>
    /// 매개변수에 있는 내용 출력
    /// </summary>
    protected void SetMessage(string message)
    {
        textMessage.text = message;
    }

    /// <summary>
    /// 입력 오류가 있는 Inputfield의 색상 변경
    /// 오류 메시지 출력
    /// </summary>
    protected void GuideForIncorrectlyEnteredData(Image image, string msg)
    {
        textMessage.text = msg;
        image.color = Color.red;
    }

    /// <summary>
    /// 필드 값이 비어있는지 확인 (image : 필드, field : 내용, result : 출력될 내용)
    /// </summary>
    protected bool IsFieldDataEmpty(Image image, string field, string result)
    {
        if (field.Trim().Equals(""))
        {
            GuideForIncorrectlyEnteredData(image, $"\"{result}\" 필드를 채워주세요.");

            return true;
        }

        return false;
    }
}

 

 다음으로는 뒤끝 서버와 연동해 로그인을 제어하는 Login 스크립트 입니다.

 

Login.cs

using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using BackEnd;
using BackEnd.Tcp;

public class Login : LoginBase
{
    [SerializeField] private Image imageID; // ID 필드 색상 변경
    [SerializeField] private TMP_InputField inputFieldID; // ID 필드 텍스트 정보 추출
    [SerializeField] private Image imagePW; // PW 필드 색상 변경
    [SerializeField] private TMP_InputField inputFieldPW; // PW 필드 텍스트 정보 추출

    [SerializeField] Button btnLogin; // 로그인 버튼 (상호작용 가능/불가능)

    /// <summary>
    /// "로그인" 버튼을 눌렀을 때 호출
    /// </summary>
    public void OnClickLogin()
    {
        // 매개변수로 입력한 InputField UI의 색상과 Message 내용 초기화
        ResetUI(imageID, imagePW);

        // 필드 값이 비어있는지 체크
        if (IsFieldDataEmpty(imageID, inputFieldID.text, "아이디")) return;
        if (IsFieldDataEmpty(imagePW, inputFieldPW.text, "비밀번호")) return;

        // 로그인 버튼 연타하지 못하도록 상호작용 비활성화
        btnLogin.interactable = false;

        // 서버에 로그인을 요청하는 동안 화면에 출력하는 내용 업데이트
        // ex) 로그인 관련 텍스트 출력, 톱니바퀴 아이콘 회전 등
        StartCoroutine(nameof(LoginProcess));

        // 뒤끝 서버 로그인 시도
        ResponseToLogin(inputFieldID.text, inputFieldPW.text);
    }

    /// <summary>
    /// 로그인 시도 후 서버로부터 전달받은 message를 기반으로 로직 처리
    /// </summary>
    private void ResponseToLogin(string ID, string PW)
    {
        // 서버에 로그인 요청 (비동기)
        Backend.BMember.CustomLogin(ID, PW, callback =>
        {
            StopCoroutine(nameof(LoginProcess));
            
            // 로그인 성공
            if (callback.IsSuccess())
            {
                SetMessage($"{inputFieldID.text}님 환영합니다.");
            }
            // 로그인 실패
            else
            {
                // 재 로그인을 위한 로그인 버튼 상호작용 활성화
                btnLogin.interactable = true;

                string message = string.Empty;

                switch(int.Parse(callback.GetStatusCode()))
                {
                    case 401: // 존재하지 않는 ID, 잘못된 비밀번호
                        message = callback.GetMessage().Contains("customId") ? "존재하지 않는 아이디입니다." : "잘못된 비밀번호 입니다.";
                        break;

                    case 403: // 유저 OR 디바이스 차단
                        message = callback.GetMessage().Contains("user") ? "차단된 유저입니다." : "차단된 디바이스입니다.";
                        break;

                    case 410: // 탈퇴 진행중
                        message = "탈퇴 진행중인 유저입니다.";
                        break;

                    default:
                        message = callback.GetMessage();
                        break;
                }

                if (message.Contains("비밀번호"))
                {
                    GuideForIncorrectlyEnteredData(imagePW, message);
                }
                else
                {
                    GuideForIncorrectlyEnteredData(imageID, message);
                }
            }
        });
    }

    private IEnumerator LoginProcess()
    {
        float time = 0;

        while (true)
        {
            time += Time.deltaTime;

            SetMessage($"로그인 중입니다. {time:F1}");

            yield return null;
        }
    }
}

 

 위와 같이 모두 작성하였으면 PopupLogin 오브젝트에 Login 컴포넌트를 추가한 후 다음과 같이 설정해줍니다. 

 

 

이 후 로그인을 위한 버튼 메서드 연결을 진행합니다. ButtonLogin 오브젝트에 OnClick() 메서드를 아래와 같이 설정합니다.

 

 

 이 후, 신을 저장하고 Logo 씬으로 이동해서 게임을 실행하면 정상적으로 Login 씬으로 이동하여 집니다.

 

 

 

반응형