반응형
플랫폼별 로그인 분기에 사용
Android, UnityEditor, Ios일때 Firebase로그인 방법을 각각 다르게 구현하여야 한다.
연습용으로 해보기 좋은 것 같아 블로그에 기록해둠.
이 패턴으로 안하면 클래스에 If문으로 나누고, 여러 매소드를 만들어서 구현하면 된다.
ex)
private void MockLogin();
private void AndroidLogin();
private void IosLogin();
📌Monobehavior 상속
비동기 처리를 위해 코루틴이 사용된다.
코루틴은 Monobehavior에서만 동작하므로 BaseLoginController는 Monobehavior를 상속하고, new가 아니라
addComponent로 씬에 추가하여야 함.
📌UnityAction 사용
비동기 과정이라 UnityAction을 이용하여 callback을 받도록 하였다. (Observer Pattern?)
📌Template Method로의 확장
BaseLoginController에 공통적으로 사용될 메소드 구현하면 Template Method가 된다.
📑LoginManager
public class LoginManager : MonoBehaviour
{
[SerializeField] private Button loginButton;
private BaseLoginController loginController; // Strategy Pattern;
private void Start()
{
#if UNITY_EDITOR
loginController = this.AddComponent<MockLoginController>();
#elif UNITY_ANDROID
loginController = this.AddComponent<AndroidLoginController>();
#elif UNITY_IOS
loginController = gameObject.AddComponent<IOSLoginController>();
#endif
Debug.Log(loginController.Init() ? "초기화 성공" : "초기화 실패");
loginButton.onClick.AddListener(delegate { loginController.TryLogin(OnLogin); });
}
private void OnLogin(bool result, string message)
{
Debug.Log($"{message}");
}
private void OnLogout(bool result, string message)
{
Debug.Log($"{message}");
}
private void OnFirebaseLogin(AuthResult result)
{
Debug.Log($"{result.Msg}");
}
}
📑BaseLoginController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class AuthResult
{
public bool Result { get; }
public string Msg { get; }
public string Uid{ get; }
public string Email{ get; }
public AuthResult(bool result, string msg)
{
Result = result;
Msg = msg;
}
public AuthResult(bool result, string msg, string uid, string email)
{
Result = result;
Msg = msg;
Uid = uid;
Email = email;
}
}
public abstract class BaseLoginController : MonoBehaviour
{
public abstract bool Init();
public abstract void TryLogin(UnityAction<bool, string> callback);
public abstract void TryLogout(UnityAction<bool, string> callback);
public abstract void TryFirebaseLogin(UnityAction<AuthResult> callback);
}
📑MockLoginController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class MockLoginController : BaseLoginController
{
public override bool Init()
{
return true;
}
public override void TryLogin(UnityAction<bool, string> callback)
{
callback.Invoke(true, "Mock Login Success");
}
public override void TryLogout(UnityAction<bool, string> callback)
{
callback.Invoke(true, "Mock Logout Success");
}
public override void TryFirebaseLogin(UnityAction<AuthResult> callback)
{
var authResult = new AuthResult(
true,
"Mock FirebaseLogin Success",
"this is mock uid",
"test@test.com"
);
callback.Invoke(authResult);
}
}
📑AndroidLoginController
using System;
using System.Collections;
using Firebase.Auth;
using GooglePlayGames.BasicApi;
using GooglePlayGames;
using UnityEngine;
using UnityEngine.Events;
public class AndroidLoginController : BaseLoginController
{
private FirebaseAuth _fbAuth;
public override bool Init()
{
Debug.Log("### LoginManager Start");
try
{
PlayGamesPlatform.InitializeInstance(new PlayGamesClientConfiguration.Builder()
.RequestIdToken()
.RequestEmail()
.Build());
PlayGamesPlatform.DebugLogEnabled = true;
PlayGamesPlatform.Activate();
_fbAuth = FirebaseAuth.DefaultInstance;
}
catch(Exception e)
{
Debug.LogException(e);
return false;
}
return true;
}
public override void TryLogin(UnityAction<bool, string> callback)
{
Debug.Log("### TryGoogleLogin");
PlayGamesPlatform.Instance.Authenticate(SignInInteractivity.CanPromptAlways, (success) =>
{
if (success == SignInStatus.Success)
{
callback.Invoke(false, "Google Login Success");
}
else
{
callback.Invoke(false, "Google Login Failure");
}
});
}
public override void TryLogout(UnityAction<bool, string> callback)
{
throw new System.NotImplementedException();
}
public override void TryFirebaseLogin(UnityAction<AuthResult> callback)
{
StartCoroutine(FirebaseLoginCoroutine(callback));
}
private IEnumerator FirebaseLoginCoroutine(UnityAction<AuthResult> callback)
{
while (string.IsNullOrEmpty(((PlayGamesLocalUser)Social.localUser).GetIdToken()))
{
yield return null;
}
var idToken = ((PlayGamesLocalUser)Social.localUser).GetIdToken();
var credential = GoogleAuthProvider.GetCredential(idToken, null);
_fbAuth.SignInWithCredentialAsync(credential).ContinueWith(task => {
if (task.IsCanceled)
{
var authResult = new AuthResult(false, "Firebase Canceled");
callback.Invoke(authResult);
}
else if (task.IsFaulted)
{
var authResult = new AuthResult(false, "Firebase Faulted");
callback.Invoke(authResult);
}
else
{
var authResult = new AuthResult(
false,
"Firebase Success",
_fbAuth.CurrentUser.UserId,
_fbAuth.CurrentUser.Email);
callback.Invoke(authResult);
}
});
}
}
📑IosLoginController
public class IosLoginController : BaseLoginController
{
public override bool Init()
{
throw new System.NotImplementedException();
}
public override void TryLogin(UnityAction<bool, string> callback)
{
throw new System.NotImplementedException();
}
public override void TryLogout(UnityAction<bool, string> callback)
{
throw new System.NotImplementedException();
}
public override void TryFirebaseLogin(UnityAction<AuthResult> callback)
{
throw new System.NotImplementedException();
}
}
지금 당장은 구현할 계획이 없지만, 나중에 필요할 때 여기만 채워넣어서 구현하면 된다.
반응형
'Unity' 카테고리의 다른 글
Character에 새 애니매이션 추가 (1) | 2023.11.19 |
---|---|
[잡담] 유니티 공부를 하면서 (0) | 2021.05.30 |
음악 중간부터 재생 (0) | 2019.04.28 |
UI Image의 크기조정 (0) | 2018.10.29 |
코루틴 콜백 받기 (0) | 2018.10.28 |