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;
}
}
}