Created
July 8, 2025 09:30
-
-
Save sathyarajshetigar/da96fb2701882980c1f7f5434e8dd6bb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if USE_PUSH | |
using OneSignalSDK.User.Models; | |
#endif | |
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Globalization; | |
using System.Net.Http; | |
using System.Threading.Tasks; | |
using DG.Tweening; | |
using IjsUiFramework; | |
using OneSignalSDK; | |
using OneSignalSDK.Debug.Models; | |
using OneSignalSDK.InAppMessages; | |
using OneSignalSDK.Notifications; | |
using OneSignalSDK.Notifications.Models; | |
using OneSignalSDK.User; | |
using Sirenix.OdinInspector; | |
using UnityEngine; | |
using UnityEngine.SceneManagement; | |
using Utils; | |
using static Msc.Facade; | |
//unity 6 android build issue solution | |
// https://github.com/OneSignal/OneSignal-Unity-SDK/issues/752 | |
namespace Managers | |
{ | |
public class OneSignalController : MonoBehaviour | |
{ | |
#region Logger | |
private readonly IJSLogger _logger = new("OneSignalController", Color.yellow); | |
[SerializeField] [BoxGroup("Logs")] private bool _enableLogs; | |
[SerializeField] [BoxGroup("Logs")] private Color _logColor; | |
private void OnValidate() | |
{ | |
_logger.ToggleLogs(_enableLogs); | |
_logger.ModifyColor(_logColor); | |
} | |
#endregion | |
private string _appID, _apiAuthKey; | |
protected OneSignalController() | |
{ | |
} | |
public static OneSignalController instance; | |
void OnEnable() | |
{ | |
PlayFabManager.onPlayfabSetupCompleteEvent += onPlayfabSetupComplete; | |
} | |
void OnDisable() | |
{ | |
PlayFabManager.onPlayfabSetupCompleteEvent -= onPlayfabSetupComplete; | |
} | |
void Awake() | |
{ | |
_logger.ToggleLogs(_enableLogs); | |
if (instance == null) | |
{ | |
instance = this; | |
DontDestroyOnLoad(gameObject); | |
} | |
else if (instance != this) | |
{ | |
Destroy(gameObject); | |
} | |
} | |
private void Start() | |
{ | |
Init(); | |
} | |
private void onPlayfabSetupComplete(bool success) | |
{ | |
Game.Log($"onPlayfabSetupComplete {success}"); | |
#if UNITY_IOS && !UNITY_EDITOR | |
if (PlayerPreference.launchCount >= 2)//don't show on first launch. there is a high chance the player will not allow the notification | |
Init(); | |
#else | |
Init(); | |
#endif | |
} | |
private void Init() | |
{ | |
#if USE_PUSH | |
// Enable the lines below to debug issues with OneSignal | |
OneSignal.Debug.LogLevel = LogLevel.Verbose; | |
OneSignal.Debug.AlertLevel = LogLevel.Fatal; | |
_appID = gameData.oneSignalID; | |
_apiAuthKey = gameData.oneSignalAPIKey; | |
_logger.PrintLog($"Initializing with appId <b>{_appID}</b>"); | |
OneSignal.Initialize(_appID); | |
// Set up the default live activity | |
OneSignal.LiveActivities.SetupDefault(); | |
// Setting ConsentRequired to true will prevent the OneSignalSDK from operating until | |
// PrivacyConsent is also set to true | |
#if UNITY_ANDROID | |
OneSignal.ConsentRequired = false; | |
#else | |
_logger.PrintLog($"Prompt For Push"); | |
if (PlayerPrefs.GetInt("dontAskAgain", 0) == 1) | |
_logger.PrintLog($"Dont Ask Again"); | |
else if (PlayerPrefs.GetInt("gavePermission", 0) == 1) | |
_logger.PrintLog($"gavePermission"); | |
else | |
{ | |
OneSignal.ConsentGiven = true; | |
OneSignal.ConsentRequired = false; | |
_logger.PrintLog($"ConsentRequired"); | |
OneSignal.User.PushSubscription.OptIn(); | |
} | |
#endif | |
// Set up the below to listen for and respond to events from notifications | |
OneSignal.Notifications.Clicked += _notificationOnClick; | |
OneSignal.Notifications.ForegroundWillDisplay += _notificationOnDisplay; | |
OneSignal.Notifications.PermissionChanged += _notificationPermissionChanged; | |
// Set up the below to listen for and respond to events from in-application messages | |
OneSignal.InAppMessages.WillDisplay += _iamWillDisplay; | |
OneSignal.InAppMessages.DidDisplay += _iamDidDisplay; | |
OneSignal.InAppMessages.WillDismiss += _iamWillDismiss; | |
OneSignal.InAppMessages.DidDismiss += _iamDidDismiss; | |
OneSignal.InAppMessages.Clicked += _iamOnClick; | |
// Set up the below to listen for and respond to state changes | |
OneSignal.User.PushSubscription.Changed += _pushSubscriptionChanged; | |
OneSignal.User.Changed += _userStateChanged; | |
var myOneSignalID = OneSignal.User.PushSubscription.Id; | |
if (!string.IsNullOrEmpty(myOneSignalID)) | |
{ | |
if (!myOneSignalID.Equals(PlayerPreference.oneSignalID)) | |
PlayerPreference.oneSignalID = myOneSignalID; | |
PlayFabManager.instance.UpdateUserData(Game.PTD_PUSHID, myOneSignalID, false); | |
} | |
else | |
Game.Log("OneSignal PushNotificationManager onPlayfabSetupComplete localUserID is null................................................"); | |
#endif | |
} | |
#if USE_PUSH | |
private void _notificationOnClick(object sender, NotificationClickEventArgs e) | |
{ | |
OnNotificationOpen(e.Notification); | |
} | |
private void OnNotificationOpen(INotification notification) | |
{ | |
_logger.PrintLog($"Notification was clicked with Notification: {JsonUtility.ToJson(notification)}"); | |
var additionalData = (Dictionary<string, object>)notification.AdditionalData; | |
foreach (var item in additionalData) | |
_logger.PrintLog($"item Key {item.Key} Value {item.Value}"); | |
if (additionalData.TryGetValue("type", out var typeObj)) | |
{ | |
var type = typeObj.ToString(); | |
switch (type) | |
{ | |
case "Invitation": | |
{ | |
if (additionalData.TryGetValue("roomCode", out var roomCodeObj) | |
&& additionalData.TryGetValue("playerName", out var playerNameObj) | |
&& additionalData.TryGetValue("senderPushID", out var senderPushIDObj)) | |
{ | |
_logger.PrintLog($"roomCodeObj: {roomCodeObj == null} playerNameObj {playerNameObj == null}"); | |
if (roomCodeObj != null && playerNameObj != null && senderPushIDObj != null) | |
{ | |
var roomCode = roomCodeObj.ToString(); | |
var playerName = playerNameObj.ToString(); | |
var senderPushID = senderPushIDObj.ToString(); | |
_logger.PrintLog($"RoomCode: {roomCode}"); | |
_logger.PrintLog($"PlayerName: {playerName}"); | |
_logger.PrintLog($"senderPushID: {senderPushID}"); | |
if (!string.IsNullOrEmpty(roomCode)) | |
{ | |
HandleNotificationResponse(playerName, roomCode, senderPushID); | |
} | |
else | |
{ | |
Game.acceptingInvite = false; | |
Game.roomName = string.Empty; | |
} | |
} | |
} | |
break; | |
} | |
case "InvitationResponse": | |
{ | |
if (additionalData.TryGetValue("response", out var responseObj)) | |
{ | |
var response = responseObj.ToString(); | |
_logger.PrintLog($"InvitationResponse received: {response}"); | |
// Get additional data for better context | |
string roomCode = ""; | |
string playerName = ""; | |
if (additionalData.TryGetValue("roomCode", out var roomCodeObj)) | |
roomCode = roomCodeObj.ToString(); | |
if (additionalData.TryGetValue("playerName", out var playerNameObj)) | |
playerName = playerNameObj.ToString(); | |
_logger.PrintLog($"InvitationResponse details - roomCode: {roomCode}, playerName: {playerName}"); | |
// Only show toast if the sender is still in a game room | |
// If roomCode is provided, check if sender is in that specific room | |
bool shouldShowToast = false; | |
if (photonManager?.inRoom ?? false) | |
{ | |
if (!string.IsNullOrEmpty(roomCode)) | |
{ | |
// Check if sender is in the same room that was invited to | |
shouldShowToast = Game.roomName.Equals(roomCode, StringComparison.OrdinalIgnoreCase); | |
_logger.PrintLog($"Room validation - Current room: {Game.roomName}, Invited room: {roomCode}, Match: {shouldShowToast}"); | |
} | |
else | |
{ | |
// Fallback: show toast if sender is in any room | |
shouldShowToast = true; | |
_logger.PrintLog("No roomCode provided, showing toast since sender is in a room"); | |
} | |
} | |
if (shouldShowToast) | |
{ | |
string toastMessage; | |
if (response.Contains("Accepted")) | |
{ | |
toastMessage = $"{playerName} {Game.GetLocTxt(LKeys.ACCEPTEDREQUEST)}"; | |
} | |
else if (response.Contains("Rejected")) | |
{ | |
toastMessage = $"{playerName} {Game.GetLocTxt(LKeys.REJREQ)}"; | |
} | |
else | |
{ | |
// Fallback: use the full message from notification | |
toastMessage = notification.Body ?? response; | |
} | |
_logger.PrintLog($"Showing invitation response toast: {toastMessage}"); | |
DialogBox.ShowToastMessage(toastMessage, 3f); | |
} | |
else | |
{ | |
_logger.PrintLog("InvitationResponse received but sender is not in the invited game room - toast not shown"); | |
} | |
} | |
break; | |
} | |
} | |
} | |
ClearPush(); | |
} | |
private void HandleNotificationResponse(string playerName, string roomCode, string senderPushID) | |
{ | |
DialogBox.ShowReplacingDialog(Game.GetLocTxt(LKeys.PRIVATEGAME), $"{playerName} {Game.GetLocTxt(LKeys.SENTUAREQUEST)}", | |
Game.GetLocTxt(LKeys.JOIN), Game.GetLocTxt(LKeys.CANCEL), (join, didcancel) => | |
{ | |
if (join) | |
{ | |
DialogBox.ShowToastMessage($"{Game.GetLocTxt(LKeys.ROOMID)} {roomCode}", 3f); | |
Game.SetGameMode(PlayModes.OnlinePrivate); | |
Game.acceptingInvite = true; | |
Game.roomName = roomCode; | |
// Fix for Bug 143: Set isNewGame to true when accepting invites from game over screen | |
// This ensures proper scene initialization and blackout panel management | |
if (Game.uiScreen >= UIScreens.PauseScreen) | |
{ | |
Game.Log($"HandleNotification: Setting isNewGame=true for invite from game screen. uiScreen={Game.uiScreen}"); | |
Game.isNewGame = true; | |
} | |
Game.Log("HandleNotification roomName : " + roomCode + " uiScreen " + Game.uiScreen + " inroom? " + | |
photonManager?.inRoom); | |
if (Game.uiScreen >= UIScreens.PauseScreen) | |
{ | |
if (photonManager?.inRoom ?? false) | |
photonManager?.Disconnect(ReloadGameSceneAndJoinTheGame); | |
else | |
ReloadGameSceneAndJoinTheGame(); | |
} | |
else if (Game.uiScreen < UIScreens.PauseScreen) | |
{ | |
gameManager.introScreenUIController?.PlayOnlinePrivate(); | |
} | |
// SendResponse(senderPushID, $"{PlayerProfile.playerName} {Game.GetLocTxt(LKeys.ACCEPTEDREQUEST)}"); | |
// SendResponse(senderPushID, $"{PlayerProfile.playerName} Accepted your request."); | |
SendInviteResponseAsync(senderPushID, $"{PlayerProfile.playerName} {Game.GetLocTxt(LKeys.ACCEPTEDREQUEST)}", "Accepted", roomCode, | |
PlayerProfile.playerName); | |
//SendResponse(senderPushID, "Accepted", ""); | |
} | |
else | |
{ | |
Game.acceptingInvite = false; | |
Game.roomName = string.Empty; | |
// SendResponse(senderPushID, $"{PlayerProfile.playerName} {Game.GetLocTxt(LKeys.REJREQ)}"); | |
// SendResponse(senderPushID, $"{PlayerProfile.playerName} Rejected your request."); | |
SendInviteResponseAsync(senderPushID, $"{PlayerProfile.playerName} {Game.GetLocTxt(LKeys.REJREQ)}", "Rejected", roomCode, | |
PlayerProfile.playerName); | |
} | |
}); | |
} | |
private void _notificationOnDisplay(object sender, NotificationWillDisplayEventArgs e) | |
{ | |
var additionalData = e.Notification.AdditionalData != null | |
? Json.Serialize(e.Notification.AdditionalData) | |
: null; | |
_logger.PrintLog($"Notification was received in foreground: {JsonUtility.ToJson(e.Notification)}\n{additionalData}"); | |
e.Notification.Display(); | |
OnNotificationOpen(e.Notification); | |
} | |
private void _notificationPermissionChanged(object sender, NotificationPermissionChangedEventArgs e) | |
{ | |
_logger.PrintLog($"Notification Permission changed to: {e.Permission}"); | |
} | |
private void _iamWillDisplay(object sender, InAppMessageWillDisplayEventArgs e) | |
{ | |
_logger.PrintLog($"IAM will display: {JsonUtility.ToJson(e.Message)}"); | |
} | |
private void _iamDidDisplay(object sender, InAppMessageDidDisplayEventArgs e) | |
{ | |
_logger.PrintLog($"IAM did display: {JsonUtility.ToJson(e.Message)}"); | |
} | |
private void _iamWillDismiss(object sender, InAppMessageWillDismissEventArgs e) | |
{ | |
_logger.PrintLog($"IAM will dismiss: {JsonUtility.ToJson(e.Message)}"); | |
} | |
private void _iamDidDismiss(object sender, InAppMessageDidDismissEventArgs e) | |
{ | |
_logger.PrintLog($"IAM did dismiss: {JsonUtility.ToJson(e.Message)}"); | |
} | |
private void _iamOnClick(object sender, InAppMessageClickEventArgs e) | |
{ | |
_logger.PrintLog($"IAM was clicked with Message: {JsonUtility.ToJson(e.Message)}"); | |
_logger.PrintLog($"IAM was clicked with Result: {JsonUtility.ToJson(e.Result)}"); | |
_logger.PrintLog($"IAM was clicked with Result UrlTarget: " + e.Result.UrlTarget); | |
} | |
private void _pushSubscriptionChanged(object sender, PushSubscriptionChangedEventArgs e) | |
{ | |
_logger.PrintLog($"Push subscription changed from previous: {JsonUtility.ToJson(e.State.Previous)}"); | |
_logger.PrintLog($"Push subscription changed to current: {JsonUtility.ToJson(e.State.Current)}"); | |
//TODO:Store it somewhere | |
//Called only once during the first launch | |
var idToStore = e.State.Current.Id; | |
_logger.PrintLog($"_pushSubscriptionChanged idToStore : {idToStore}"); | |
PlayerPreference.oneSignalID = idToStore; | |
} | |
private void _userStateChanged(object sender, UserStateChangedEventArgs e) | |
{ | |
_logger.PrintLog($"OneSignalId changed : {e.State.Current.OneSignalId}"); | |
_logger.PrintLog($"ExternalId changed : {e.State.Current.ExternalId}"); | |
if (!string.IsNullOrEmpty(e.State.Current.OneSignalId)) | |
_logger.PrintLog("OneSignalIdReceived: " + e.State.Current.OneSignalId); | |
else | |
_logger.PrintLog("PushNotificationManager localUserID is null"); | |
} | |
private void ClearPush() | |
{ | |
_logger.PrintLog("Clearing existing OneSignal push notifications"); | |
OneSignal.Notifications.ClearAllNotifications(); | |
_logger.PrintLog("Notifications cleared"); | |
} | |
#endif | |
public async Task<bool> InviteAsync(string toUserID, string message, string roomCode, string playerName, string senderPushID) | |
{ | |
try | |
{ | |
#if USE_PUSH | |
// Validate configuration | |
if (string.IsNullOrEmpty(_appID) || string.IsNullOrEmpty(_apiAuthKey)) | |
{ | |
_logger.PrintLog("OneSignal configuration is missing. App ID or API Key is empty."); | |
DialogBox.ShowToastMessage(Game.GetLocTxt(LKeys.INVITEFAILED)); | |
return false; | |
} | |
// Validate target user ID | |
if (string.IsNullOrEmpty(toUserID)) | |
{ | |
_logger.PrintLog("Cannot send invite: Target user OneSignal ID is null or empty."); | |
//DialogBox.ShowToastMessage("Cannot send invite. User is not available for notifications."); | |
DialogBox.ShowToastMessage(Game.GetLocTxt(LKeys.INVITEFAILED)); | |
return false; | |
} | |
_logger.PrintLog( | |
$"InviteAsync toUserID: {toUserID}, message: {message}, roomCode: {roomCode}, playerName: {playerName}, senderPushID: {senderPushID}"); | |
_logger.PrintLog($"Using App ID: {_appID}"); | |
var client = new HttpClient(); | |
client.Timeout = TimeSpan.FromSeconds(30); // Set 30 second timeout to prevent hanging | |
var request = new HttpRequestMessage(HttpMethod.Post, "https://onesignal.com/api/v1/notifications"); | |
// Use the correct authorization header format for OneSignal REST API | |
request.Headers.Add("Authorization", $"Basic {_apiAuthKey}"); | |
request.Headers.Add("Accept", "application/json"); | |
var pushOptions = new Dictionary<string, object> | |
{ | |
["contents"] = new Dictionary<string, string> { ["en"] = message }, | |
["data"] = new Dictionary<string, string> | |
{ | |
["type"] = "Invitation", | |
["roomCode"] = roomCode, | |
["playerName"] = playerName, | |
["senderPushID"] = senderPushID, | |
}, | |
["include_subscription_ids"] = new List<string> { toUserID }, | |
["app_id"] = _appID | |
}; | |
var jsonPayload = Json.Serialize(pushOptions); | |
_logger.PrintLog($"Request payload: {jsonPayload}"); | |
var content = new StringContent(jsonPayload, System.Text.Encoding.UTF8, "application/json"); | |
request.Content = content; | |
var response = await client.SendAsync(request); | |
var resultMessage = await response.Content.ReadAsStringAsync(); | |
_logger.PrintLog($"Response status: {response.StatusCode}"); | |
_logger.PrintLog($"Response content: {resultMessage}"); | |
if (response.IsSuccessStatusCode) | |
{ | |
_logger.PrintLog("Successfully sent invite notification"); | |
return true; | |
} | |
else | |
{ | |
_logger.PrintLog($"Request failed with status code: {response.StatusCode} and message: {resultMessage}"); | |
// Provide more specific error messages based on status code | |
// string userMessage = response.StatusCode switch | |
// { | |
// System.Net.HttpStatusCode.Unauthorized => "Authentication failed. Please check OneSignal configuration.", | |
// System.Net.HttpStatusCode.Forbidden => "Access denied. Please verify OneSignal API key permissions.", | |
// System.Net.HttpStatusCode.BadRequest => "Invalid request. Please check the notification data.", | |
// _ => "Invite failed. Please try again later." | |
// }; | |
//DialogBox.ShowToastMessage(userMessage); | |
return false; | |
} | |
#endif | |
} | |
catch (TaskCanceledException e) when (e.InnerException is TimeoutException) | |
{ | |
_logger.PrintLog($"Notifications Invite Timeout: {e.Message}"); | |
DialogBox.ShowToastMessage(Game.GetLocTxt(LKeys.INVITEFAILED)); | |
// DialogBox.ShowToastMessage("Request timed out. Please try again."); | |
return false; | |
} | |
catch (HttpRequestException e) | |
{ | |
_logger.PrintLog($"Notifications Invite Network Error: {e.Message}"); | |
DialogBox.ShowToastMessage(Game.GetLocTxt(LKeys.INVITEFAILED)); | |
// DialogBox.ShowToastMessage("Network error. Please check your connection."); | |
return false; | |
} | |
catch (Exception e) | |
{ | |
_logger.PrintLog($"Notifications Invite Failed: {e.Message}"); | |
_logger.PrintLog($"Stack trace: {e.StackTrace}"); | |
DialogBox.ShowToastMessage(Game.GetLocTxt(LKeys.INVITEFAILED)); | |
// DialogBox.ShowToastMessage("Unexpected error occurred. Please try again."); | |
return false; | |
} | |
} | |
private async void SendInviteResponseAsync(string toUserID, string message, string response, string roomCode = "", string playerName = "") | |
{ | |
try | |
{ | |
#if USE_PUSH | |
// Validate configuration | |
if (string.IsNullOrEmpty(_appID) || string.IsNullOrEmpty(_apiAuthKey)) | |
{ | |
_logger.PrintLog("OneSignal configuration is missing. App ID or API Key is empty."); | |
return; | |
} | |
// Validate target user ID | |
if (string.IsNullOrEmpty(toUserID)) | |
{ | |
_logger.PrintLog("Cannot send invite response: Target user OneSignal ID is null or empty."); | |
return; | |
} | |
_logger.PrintLog( | |
$"SendInviteResponseAsync toUserID: {toUserID}, message: {message}, response: {response}, roomCode: {roomCode}, playerName: {playerName}"); | |
var client = new HttpClient(); | |
client.Timeout = TimeSpan.FromSeconds(30); // Set 30 second timeout to prevent hanging | |
var request = new HttpRequestMessage(HttpMethod.Post, "https://onesignal.com/api/v1/notifications"); | |
// Use the correct authorization header format for OneSignal REST API | |
request.Headers.Add("Authorization", $"Basic {_apiAuthKey}"); | |
request.Headers.Add("Accept", "application/json"); | |
var pushOptions = new Dictionary<string, object> | |
{ | |
["contents"] = new Dictionary<string, string> { ["en"] = message }, | |
["data"] = new Dictionary<string, string> | |
{ | |
["type"] = "InvitationResponse", | |
["response"] = response, | |
["roomCode"] = roomCode, | |
["playerName"] = playerName | |
}, | |
["include_subscription_ids"] = new List<string> { toUserID }, | |
["app_id"] = _appID // Use the configured App ID instead of hardcoded value | |
}; | |
var jsonPayload = Json.Serialize(pushOptions); | |
_logger.PrintLog($"Response payload: {jsonPayload}"); | |
var content = new StringContent(jsonPayload, System.Text.Encoding.UTF8, "application/json"); | |
request.Content = content; | |
var responseMessage = await client.SendAsync(request); | |
var resultMessage = await responseMessage.Content.ReadAsStringAsync(); | |
_logger.PrintLog($"Response status: {responseMessage.StatusCode}"); | |
_logger.PrintLog($"Response content: {resultMessage}"); | |
if (!responseMessage.IsSuccessStatusCode) | |
{ | |
_logger.PrintLog($"Failed to send invite response with status code: {responseMessage.StatusCode}"); | |
} | |
else | |
{ | |
_logger.PrintLog("Successfully sent invite response notification"); | |
} | |
#endif | |
} | |
catch (TaskCanceledException e) when (e.InnerException is TimeoutException) | |
{ | |
_logger.PrintLog($"SendInviteResponseAsync Timeout: {e.Message}"); | |
} | |
catch (HttpRequestException e) | |
{ | |
_logger.PrintLog($"SendInviteResponseAsync Network Error: {e.Message}"); | |
} | |
catch (Exception e) | |
{ | |
_logger.PrintLog($"SendInviteResponseAsync failed: {e.Message}"); | |
_logger.PrintLog($"Stack trace: {e.StackTrace}"); | |
} | |
} | |
private void ReloadGameSceneAndJoinTheGame() | |
{ | |
StartCoroutine("ReloadGameSceneAndJoinTheGameNow"); | |
} | |
IEnumerator ReloadGameSceneAndJoinTheGameNow() | |
{ | |
Game.Log($"Reloading the game scene now to join the private game {Game.roomName}. isNewGame={Game.isNewGame}"); | |
DialogBox.ShowLoadingScreen(Game.GetLocTxt(LKeys.PLEASEWAIT)); | |
// Additional safeguard: Ensure isNewGame is true when reloading scene for invitations | |
// This prevents the black screen issue in Bug 143 | |
if (Game.acceptingInvite && !Game.isNewGame) | |
{ | |
Game.Log("ReloadGameSceneAndJoinTheGameNow: Force setting isNewGame=true for invitation flow"); | |
Game.isNewGame = true; | |
} | |
yield return new WaitForSeconds(1f); | |
SceneManager.LoadSceneAsync(Game.GAMESCENENAME, LoadSceneMode.Single); | |
SceneManager.LoadSceneAsync(Game.GAMESCENEHUDNAME, LoadSceneMode.Additive); | |
Game.GCCollect(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment