342 lines
12 KiB
C#
342 lines
12 KiB
C#
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Threading.Tasks;
|
||
|
using TMPro;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.SceneManagement;
|
||
|
|
||
|
namespace BulletHellTemplate
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// Manages user authentication and related UI operations.
|
||
|
/// Delegates login/create account to FirebaseAuthManager and data loading to the same manager,
|
||
|
/// which calls FirebaseManager internally.
|
||
|
/// </summary>
|
||
|
public class AuthManager : MonoBehaviour
|
||
|
{
|
||
|
[Header("UI Elements")]
|
||
|
[Tooltip("Input field for user email during login.")]
|
||
|
public TMP_InputField loginEmailInputField;
|
||
|
|
||
|
[Tooltip("Input field for user password during login.")]
|
||
|
public TMP_InputField loginPasswordInputField;
|
||
|
|
||
|
[Tooltip("Input field for user email during account creation.")]
|
||
|
public TMP_InputField createEmailInputField;
|
||
|
|
||
|
[Tooltip("Input field for user password during account creation.")]
|
||
|
public TMP_InputField createPasswordInputField;
|
||
|
|
||
|
[Tooltip("UI text element to display status messages.")]
|
||
|
public TextMeshProUGUI statusText;
|
||
|
|
||
|
[Header("UI Prefabs")]
|
||
|
[Tooltip("UI Prefab for login screen.")]
|
||
|
public GameObject UILoginPrefab;
|
||
|
|
||
|
[Tooltip("UI Prefab for loading indicator.")]
|
||
|
public GameObject UILoading;
|
||
|
|
||
|
[Tooltip("Text element for loading animations and status messages.")]
|
||
|
public TextMeshProUGUI loadingText;
|
||
|
|
||
|
[Header("Scene Management")]
|
||
|
[Tooltip("Name of the scene to load after successful authentication.")]
|
||
|
public string HomeSceneName;
|
||
|
|
||
|
private bool isInitialized = false;
|
||
|
private string loadingStatus = "Initializing...";
|
||
|
|
||
|
/// <summary>
|
||
|
/// Called on startup. Begins initialization of the authentication system and waits for it to complete.
|
||
|
/// </summary>
|
||
|
private async void Start()
|
||
|
{
|
||
|
UILoading.SetActive(true);
|
||
|
UpdateLoadingStatus("Starting initialization...");
|
||
|
|
||
|
await InitializeAuthSystem();
|
||
|
await WaitForSystemInitialization();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Initializes the AuthManager (local setup).
|
||
|
/// </summary>
|
||
|
private async Task InitializeAuthSystem()
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
isInitialized = true;
|
||
|
UpdateLoadingStatus("AuthManager initialized successfully.");
|
||
|
}
|
||
|
catch (Exception e)
|
||
|
{
|
||
|
Debug.LogError("Failed to initialize AuthManager: " + e.Message);
|
||
|
StartCoroutine(DisplayStatusMessage("Failed to initialize Auth system.", UnityEngine.Color.red));
|
||
|
}
|
||
|
await Task.CompletedTask;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Waits until this AuthManager and FirebaseAuthManager are fully initialized.
|
||
|
/// </summary>
|
||
|
private async Task WaitForSystemInitialization()
|
||
|
{
|
||
|
StartCoroutine(AnimateLoadingText());
|
||
|
|
||
|
while (!isInitialized ||
|
||
|
(FirebaseAuthManager.Singleton == null || !FirebaseAuthManager.Singleton.IsInitialized()))
|
||
|
{
|
||
|
UpdateLoadingStatus("Waiting for authentication systems to initialize...");
|
||
|
await Task.Delay(100);
|
||
|
}
|
||
|
|
||
|
UpdateLoadingStatus("Systems initialized successfully.");
|
||
|
await CheckUserLoginStatus();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Animates the loading text to simulate a progress indicator.
|
||
|
/// </summary>
|
||
|
private IEnumerator AnimateLoadingText()
|
||
|
{
|
||
|
int dotCount = 0;
|
||
|
while (UILoading.activeSelf)
|
||
|
{
|
||
|
string dots = new string('.', dotCount);
|
||
|
loadingText.text = $"Loading{dots}\n{loadingStatus}";
|
||
|
dotCount = (dotCount + 1) % 4;
|
||
|
yield return new WaitForSeconds(0.5f);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Updates the loading status message displayed on the UI.
|
||
|
/// </summary>
|
||
|
private void UpdateLoadingStatus(string status)
|
||
|
{
|
||
|
loadingStatus = status;
|
||
|
loadingText.text = $"Loading...\n{loadingStatus}";
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Checks if the user is already logged in. If so, loads player data and switches scenes.
|
||
|
/// Otherwise, shows the login UI.
|
||
|
/// </summary>
|
||
|
private async Task CheckUserLoginStatus()
|
||
|
{
|
||
|
var currentUser = FirebaseAuthManager.Singleton.GetCurrentUser();
|
||
|
if (currentUser != null)
|
||
|
{
|
||
|
UILoginPrefab.SetActive(false);
|
||
|
UpdateLoadingStatus("Loading player data...");
|
||
|
await LoadPlayerDataAndSwitchScene();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
UpdateLoadingStatus("Waiting for user to log in...");
|
||
|
UILoginPrefab.SetActive(true);
|
||
|
UILoading.SetActive(false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Called by the UI button to log in with email and password.
|
||
|
/// </summary>
|
||
|
public void OnLoginWithEmailButton()
|
||
|
{
|
||
|
StartCoroutine(LoginWithEmailCoroutine());
|
||
|
}
|
||
|
|
||
|
private IEnumerator LoginWithEmailCoroutine()
|
||
|
{
|
||
|
var task = LoginWithEmail();
|
||
|
while (!task.IsCompleted)
|
||
|
{
|
||
|
yield return null;
|
||
|
}
|
||
|
if (task.Exception != null)
|
||
|
{
|
||
|
Debug.LogError("Error during login with email: " + task.Exception);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Logs in the user with email and password by delegating to FirebaseAuthManager.
|
||
|
/// </summary>
|
||
|
private async Task LoginWithEmail()
|
||
|
{
|
||
|
string email = loginEmailInputField.text;
|
||
|
string password = loginPasswordInputField.text;
|
||
|
|
||
|
if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(password))
|
||
|
{
|
||
|
StartCoroutine(DisplayStatusMessage("Please enter both email and password.", UnityEngine.Color.red));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
UILoading.SetActive(true);
|
||
|
UpdateLoadingStatus("Logging in...");
|
||
|
|
||
|
try
|
||
|
{
|
||
|
await FirebaseAuthManager.Singleton.LoginWithEmailAsync(email, password);
|
||
|
StartCoroutine(DisplayStatusMessage("Login successful.", UnityEngine.Color.green));
|
||
|
UILoginPrefab.SetActive(false);
|
||
|
|
||
|
await LoadPlayerDataAndSwitchScene();
|
||
|
}
|
||
|
catch (Exception ex)
|
||
|
{
|
||
|
UILoading.SetActive(false);
|
||
|
StartCoroutine(DisplayStatusMessage("Login failed: " + ex.Message, UnityEngine.Color.red));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Called by the UI button to log in anonymously.
|
||
|
/// </summary>
|
||
|
public void OnLoginAnonymouslyButton()
|
||
|
{
|
||
|
StartCoroutine(LoginAnonymouslyCoroutine());
|
||
|
}
|
||
|
|
||
|
private IEnumerator LoginAnonymouslyCoroutine()
|
||
|
{
|
||
|
var task = LoginAnonymously();
|
||
|
while (!task.IsCompleted)
|
||
|
{
|
||
|
yield return null;
|
||
|
}
|
||
|
if (task.Exception != null)
|
||
|
{
|
||
|
Debug.LogError("Error during anonymous login: " + task.Exception);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Logs in the user anonymously by delegating to FirebaseAuthManager.
|
||
|
/// </summary>
|
||
|
private async Task LoginAnonymously()
|
||
|
{
|
||
|
UILoading.SetActive(true);
|
||
|
UpdateLoadingStatus("Logging in anonymously...");
|
||
|
|
||
|
try
|
||
|
{
|
||
|
await FirebaseAuthManager.Singleton.LoginAnonymouslyAsync();
|
||
|
StartCoroutine(DisplayStatusMessage("Anonymous login successful.", UnityEngine.Color.green));
|
||
|
UILoginPrefab.SetActive(false);
|
||
|
|
||
|
await LoadPlayerDataAndSwitchScene();
|
||
|
}
|
||
|
catch (Exception ex)
|
||
|
{
|
||
|
UILoading.SetActive(false);
|
||
|
StartCoroutine(DisplayStatusMessage("Anonymous login failed: " + ex.Message, UnityEngine.Color.red));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Called by the UI button to create a new account.
|
||
|
/// </summary>
|
||
|
public void OnCreateAccountButton()
|
||
|
{
|
||
|
StartCoroutine(CreateAccountCoroutine());
|
||
|
}
|
||
|
|
||
|
private IEnumerator CreateAccountCoroutine()
|
||
|
{
|
||
|
var task = CreateAccount();
|
||
|
while (!task.IsCompleted)
|
||
|
{
|
||
|
yield return null;
|
||
|
}
|
||
|
if (task.Exception != null)
|
||
|
{
|
||
|
Debug.LogError("Error during account creation: " + task.Exception);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Creates a new user account by delegating to FirebaseAuthManager, then loads data.
|
||
|
/// </summary>
|
||
|
private async Task CreateAccount()
|
||
|
{
|
||
|
string email = createEmailInputField.text;
|
||
|
string password = createPasswordInputField.text;
|
||
|
|
||
|
if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(password))
|
||
|
{
|
||
|
StartCoroutine(DisplayStatusMessage("Please enter email and password.", UnityEngine.Color.red));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
UILoading.SetActive(true);
|
||
|
UpdateLoadingStatus("Creating account...");
|
||
|
|
||
|
try
|
||
|
{
|
||
|
await FirebaseAuthManager.Singleton.CreateAccountAsync(email, password);
|
||
|
StartCoroutine(DisplayStatusMessage("Account created successfully.", UnityEngine.Color.green));
|
||
|
UILoginPrefab.SetActive(false);
|
||
|
|
||
|
await LoadPlayerDataAndSwitchScene();
|
||
|
}
|
||
|
catch (Exception ex)
|
||
|
{
|
||
|
UILoading.SetActive(false);
|
||
|
StartCoroutine(DisplayStatusMessage("Account creation failed: " + ex.Message, UnityEngine.Color.red));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Loads player data (through FirebaseAuthManager which calls FirebaseManager) and switches scene.
|
||
|
/// Keeps UILoading active until complete.
|
||
|
/// </summary>
|
||
|
private async Task LoadPlayerDataAndSwitchScene()
|
||
|
{
|
||
|
var currentUser = FirebaseAuthManager.Singleton.GetCurrentUser();
|
||
|
if (currentUser == null)
|
||
|
{
|
||
|
UILoading.SetActive(false);
|
||
|
StartCoroutine(DisplayStatusMessage("No user is logged in.", UnityEngine.Color.red));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
try
|
||
|
{
|
||
|
UpdateLoadingStatus("Loading player data...");
|
||
|
string loadResult = await FirebaseAuthManager.Singleton.LoadPlayerDataAsync();
|
||
|
|
||
|
loadingText.text = loadResult;
|
||
|
if (loadResult == "Player data loaded successfully.")
|
||
|
{
|
||
|
SceneManager.LoadScene(HomeSceneName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
UILoading.SetActive(false);
|
||
|
StartCoroutine(DisplayStatusMessage(loadResult, UnityEngine.Color.red));
|
||
|
}
|
||
|
}
|
||
|
catch (Exception ex)
|
||
|
{
|
||
|
UILoading.SetActive(false);
|
||
|
StartCoroutine(DisplayStatusMessage("Failed to load player data: " + ex.Message, UnityEngine.Color.red));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Displays a status message for 3 seconds and then clears it.
|
||
|
/// </summary>
|
||
|
private IEnumerator DisplayStatusMessage(string message, UnityEngine.Color color)
|
||
|
{
|
||
|
statusText.text = message;
|
||
|
statusText.color = color;
|
||
|
yield return new WaitForSeconds(3f);
|
||
|
statusText.text = string.Empty;
|
||
|
}
|
||
|
}
|
||
|
}
|