using System; using Unity.Services.Authentication; using UnityEngine; /// /// A stable, per-install unique player id that survives application restarts, so the server can recognise a /// returning client across sessions (the NGO clientId is ephemeral and reused). /// /// Primary source is the UGS anonymous PlayerId, which is already cached /// per machine AND namespaced per install via the auth profile (see OnlineSessionManager.ProfileForThisInstall), /// so it is restart-stable and stays distinct even for same-machine clone tests. When there was no UGS sign-in /// (pure loopback / offline play) it falls back to a locally generated GUID persisted in PlayerPrefs. /// public static class PersistentPlayerId { private const string PrefKey = "chameleon.persistentPlayerId"; private static string _ugsId; // authoritative once signed in; cached permanently private static string _localFallback; // loopback/offline only /// The persistent id for THIS install. Stable across restarts, never null/empty. Prefers the /// signed-in UGS id (the send path runs after sign-in, so online clients always report that); only pure /// loopback play resolves the local fallback. public static string Value { get { if (!string.IsNullOrEmpty(_ugsId)) return _ugsId; // AuthenticationService.Instance throws if UGS was never initialised (loopback) - guard it. try { var auth = AuthenticationService.Instance; if (auth != null && auth.IsSignedIn && !string.IsNullOrEmpty(auth.PlayerId)) return _ugsId = auth.PlayerId; } catch (Exception) { /* services not initialised - use the local fallback */ } return LocalFallback(); } } // NOT cached into _ugsId: a later signed-in read must be able to upgrade to the authoritative UGS id. // The fallback itself is restart-stable (PlayerPrefs), which is all offline play needs. private static string LocalFallback() { if (!string.IsNullOrEmpty(_localFallback)) return _localFallback; _localFallback = PlayerPrefs.GetString(PrefKey, ""); if (string.IsNullOrEmpty(_localFallback)) { _localFallback = Guid.NewGuid().ToString("N"); PlayerPrefs.SetString(PrefKey, _localFallback); PlayerPrefs.Save(); } return _localFallback; } }