Hello, Forum
I tried writing a login system using the Authentication Unity Player account following some Random YouTube videos. It works perfectly fine except that I am unable to implement the Sign Out system.
I tried using:
AuthenticationService.Instance.SignOut(true);
AuthenticationService.Instance.ClearSessionToken();
These two seem not working as I wish they would and respond with:
PlayerAccountsException: Player is already signed in. Unity.Services.Authentication.PlayerAccounts.PlayerAccountServiceInternal.StartSignInAsync (System.Boolean isSigningUp)
When I try to click on that function and re-login again with the Unity player account.
Is anyone familiar with this problem and have some suggestions that would help me complete this function?
Post your full code. Perhaps you are not awaiting the call properly or not catching and handling exceptions?
SignOut(true) is all you need to run. ClearSessionToken is implied by the true parameter, so you ought to remove that call.
Note however that this will prevent automatic sign-in using anonymous sign in which creates additional friction as the user has to purposefully click on the sign-in service button, or enter username/password, every time the app launches.
ClearSessionToken is unnecessary as I pointed out due to the SignOut(true) parameter.
Deleting all playerprefs is just brutal and if you or any asset you may be using in the future stores anything in PlayerPrefs you’ll not necessarily remember that you’re deleting them on sign out. Or why.
Instead, you ought to leave that to whichever script registers for the signed out event, and that script should only delete the specific keys that it is responsible for.
You have to await GetPlayerInfoAsync first or you’ll not get the current player info. It might even be null before calling GetPlayerInfoAsync.
I think that is your problem. You reveice the SignedIn event but SignedInWithUnity then calls await SignInWithUnityAsync(accessToken);
If you weren’t getting the “already signed in” exception you’d actually have an infinite loop here.
Be sure to debug this as your code executes because that would have been easy to catch with a quick debug session.
If you don’t mind me asking more questions.
In this case, I want the user to be able to access the app automatically after the first time logging in with a Unity account, how do I do?
Simply don’t clear the session token because that’s what this token is used for: to restore the player’s identity.
If a session token exists then the next time you sign in anonymously it will sign in the player using the previously used credentials.
This means either the linked account or if the account isn’t linked it will sign in the same anonymous player so that player retains progress and can still link the account with an ID provider.
Hi, I am having the similar issue, I am not sure how to resolve it. I am getting the same error after logging out and then trying to log in again. These are my 3 relevant scripts
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using Unity.Services.Authentication;
using UnityEngine;
using UnityEngine.UI;
public class UILogin : MonoBehaviour
{
[SerializeField] private Button loginButton;
// [SerializeField] private TMP_Text userIdText;
[SerializeField] private Transform loginPanel, introPanel;
[SerializeField] private LoginController loginController;
private void OnEnable()
{
loginButton.onClick.AddListener(LoginButtonPressed);
loginController.OnSingedIn += loginController_OnSingedIn;
}
private void loginController_OnSingedIn(PlayerInfo playerInfo, string playerName)
{
loginPanel.gameObject.SetActive(false);
introPanel.gameObject.SetActive(true);
// userIdText.text = $"id_{playerInfo.Id}";
Debug.Log(playerName);
}
private async void LoginButtonPressed()
{
await loginController.InitSignIn();
}
private void OnDisable()
{
loginButton.onClick.RemoveListener(LoginButtonPressed);
loginController.OnSingedIn -= loginController_OnSingedIn;
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Services.Authentication;
using Unity.Services.Authentication.PlayerAccounts;
using Unity.Services.Core;
using UnityEngine;
using System.Threading.Tasks;
public class LoginController : MonoBehaviour
{
//Login i cloud save
public static string[] collectedStickers = { };
public static int brojPackova = 3;
public event Action<PlayerInfo, string> OnSingedIn;
private PlayerInfo playerInfo;
async void Awake()
{
await UnityServices.InitializeAsync();
PlayerAccountService.Instance.SignedIn += SignedIn;
if (PlayerPrefs.HasKey("PlayerToken"))
{
await SignInWithUnityAsync(PlayerPrefs.GetString("PlayerToken"));
}
}
public async void SignedIn()
{
try
{
var accessToken = PlayerAccountService.Instance.AccessToken;
PlayerPrefs.SetString("PlayerToken", accessToken);
PlayerPrefs.Save();
await SignInWithUnityAsync(accessToken);
}
catch (Exception ex)
{
}
}
public async Task InitSignIn()
{
await PlayerAccountService.Instance.StartSignInAsync();
}
async Task SignInWithUnityAsync(string accessToken)
{
try
{
await AuthenticationService.Instance.SignInWithUnityAsync(accessToken);
Debug.Log("SignIn is successful.");
playerInfo = AuthenticationService.Instance.PlayerInfo;
var name = await AuthenticationService.Instance.GetPlayerNameAsync();
OnSingedIn?.Invoke(playerInfo, name);
//pozvati load
try
{
GetComponent<CloudSave>().LoadData();
} catch (Exception ex)
{
Debug.Log(ex);
}
}
catch (AuthenticationException ex)
{
// Compare error code to AuthenticationErrorCodes
// Notify the player with the proper error message
Debug.LogException(ex);
}
catch (RequestFailedException ex)
{
// Compare error code to CommonErrorCodes
// Notify the player with the proper error message
Debug.LogException(ex);
}
}
private void OnDestroy()
{
Debug.Log("Destroyed");
PlayerAccountService.Instance.SignedIn -= SignedIn;
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Services.Authentication;
using Unity.Services.Authentication.PlayerAccounts;
using Unity.Services.Core;
using UnityEngine;
using System.Threading.Tasks;
using UnityEngine.SceneManagement;
public class LogOut : MonoBehaviour
{
public void Logout()
{
AuthenticationService.Instance.SignOut(true);
PlayerPrefs.DeleteKey("PlayerToken");
PlayerPrefs.Save();
Debug.Log("User logged out and token deleted.");
SceneManager.LoadScene("Login");
}
}
LogOut script is connected to a button that is in another scene.