app.hypergames.hypersdk 1.4.19 → 1.4.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## [1.4.20](https://github.com/mvmhyper/hyper-sdk/compare/v1.4.19...v1.4.20) (2026-01-12)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Add custom restart flow and improve default restart for async scenes ([72c6d78](https://github.com/mvmhyper/hyper-sdk/commit/72c6d781b485503b98acc028294015db3cf93474))
7
+
1
8
  ## [1.4.19](https://github.com/mvmhyper/hyper-sdk/compare/v1.4.18...v1.4.19) (2026-01-06)
2
9
 
3
10
 
@@ -110,6 +110,31 @@ namespace Hyper.Editor
110
110
  EditorGUILayout.Space(-1f);
111
111
  DrawPreviewImage();
112
112
 
113
+ // Draw Restart Flow Settings
114
+ EditorGUILayout.Space(12);
115
+ EditorGUILayout.LabelField("Restart Flow Settings", EditorStyles.boldLabel);
116
+
117
+ EditorGUILayout.BeginVertical(EditorStyles.helpBox);
118
+ {
119
+ EditorGUILayout.LabelField(
120
+ "Enable custom restart flow if your game has its own restart logic. " +
121
+ "When enabled, SDK will fire OnCustomRestart event instead of using default restart.",
122
+ EditorStyles.wordWrappedMiniLabel);
123
+
124
+ // if (settings.useCustomRestartFlow)
125
+ // {
126
+ // EditorGUILayout.Space(4);
127
+ // EditorGUILayout.HelpBox(
128
+ // "Custom restart enabled. Subscribe to HyperSDK.Event.OnCustomRestart in your game manager:\n" +
129
+ // "HyperSDK.Event.OnCustomRestart += YourRestartMethod;",
130
+ // MessageType.Info);
131
+ // }
132
+ }
133
+ EditorGUILayout.EndVertical();
134
+ settings.useCustomRestartFlow = EditorGUILayout.Toggle(
135
+ new GUIContent("Use Custom Restart Flow"),
136
+ settings.useCustomRestartFlow);
137
+
113
138
  EditorGUILayout.Space(12);
114
139
  // Draw Editor Testing
115
140
  SerializedProperty settingsProp = serializedObject.FindProperty("_settings");
@@ -1,4 +1,6 @@
1
1
  using System;
2
+ using System.Collections;
3
+ using System.Collections.Generic;
2
4
  using UnityEngine;
3
5
  using UnityEngine.SceneManagement;
4
6
  using Hyper.Internal.Managers;
@@ -44,15 +46,90 @@ namespace Hyper.Internal
44
46
  ///
45
47
  /// This is the internal implementation used by both the public
46
48
  /// HyperSDK facade and internal UI flows (pause/game over modals).
49
+ ///
50
+ /// If useCustomRestartFlow is enabled in settings, fires OnCustomRestart event
51
+ /// instead of performing default restart. Otherwise, performs improved default
52
+ /// restart that properly unloads all scenes (including additive) before reloading.
47
53
  /// </summary>
48
54
  internal static void RestartSession()
49
55
  {
50
56
  _isSoftRestarting = true;
51
57
 
58
+ if (_settings != null && _settings.useCustomRestartFlow)
59
+ {
60
+ _eventManager?.InvokeCustomRestartEvent();
61
+ return;
62
+ }
63
+
64
+ // Use improved default restart flow
65
+ if (_host != null)
66
+ {
67
+ _host.StartCoroutine(RestartSessionCoroutine());
68
+ }
69
+ else
70
+ {
71
+ // Fallback to immediate restart if host doesn't exist
72
+ ClearAllDontDestroyOnLoadObjects();
73
+ SceneManager.LoadScene("HyperLoader");
74
+ }
75
+ }
76
+
77
+ /// <summary>
78
+ /// Coroutine-based restart that properly unloads all scenes before reloading.
79
+ /// Handles async scene operations and ensures clean state before restart.
80
+ /// </summary>
81
+ private static IEnumerator RestartSessionCoroutine()
82
+ {
83
+ yield return UnloadAllScenesCoroutine();
84
+
52
85
  ClearAllDontDestroyOnLoadObjects();
53
86
  SceneManager.LoadScene("HyperLoader");
54
87
  }
55
88
 
89
+ /// <summary>
90
+ /// Unloads all additive scenes. The active (single) scene will be replaced when HyperLoader loads.
91
+ /// Waits for all async unload operations to complete before proceeding.
92
+ /// </summary>
93
+ private static IEnumerator UnloadAllScenesCoroutine()
94
+ {
95
+ List<AsyncOperation> unloadOps = new List<AsyncOperation>();
96
+ Scene activeScene = SceneManager.GetActiveScene();
97
+
98
+ // Only unload additive scenes (not the active single scene)
99
+ for (int i = SceneManager.sceneCount - 1; i >= 0; i--)
100
+ {
101
+ Scene scene = SceneManager.GetSceneAt(i);
102
+
103
+ if (scene.name == "HyperLoader")
104
+ continue;
105
+
106
+ if (scene == activeScene)
107
+ continue;
108
+
109
+ // Only unload additive scenes that are loaded
110
+ if (scene.isLoaded)
111
+ {
112
+ AsyncOperation unloadOp = SceneManager.UnloadSceneAsync(scene);
113
+ if (unloadOp != null)
114
+ {
115
+ unloadOps.Add(unloadOp);
116
+ }
117
+ }
118
+ }
119
+
120
+ // Wait for all unload operations to complete
121
+ foreach (AsyncOperation op in unloadOps)
122
+ {
123
+ while (op != null && !op.isDone)
124
+ {
125
+ yield return null;
126
+ }
127
+ }
128
+
129
+ Resources.UnloadUnusedAssets();
130
+ yield return null;
131
+ }
132
+
56
133
  internal static void Initialize(Action callback)
57
134
  {
58
135
  ValidatePlatform();
@@ -29,6 +29,7 @@ namespace Hyper.Internal.Managers
29
29
  public event Action OnGameEnded;
30
30
  public event Action OnLivesExhausted;
31
31
  public event Action OnHealthExhausted;
32
+ public event Action OnCustomRestart;
32
33
 
33
34
  #endregion
34
35
 
@@ -62,6 +63,7 @@ namespace Hyper.Internal.Managers
62
63
  internal void InvokeGameEndedEvent() => OnGameEnded?.Invoke();
63
64
  internal void InvokeLivesExhaustedEvent() => OnLivesExhausted?.Invoke();
64
65
  internal void InvokeHealthExhaustedEvent() => OnHealthExhausted?.Invoke();
66
+ internal void InvokeCustomRestartEvent() => OnCustomRestart?.Invoke();
65
67
  internal void InvokeConnectionLostEvent() => OnInternetConnectionLost?.Invoke();
66
68
  internal void InvokeConnectionFoundEvent() => OnInternetConnectionFound?.Invoke();
67
69
  internal void InvokeTutorialLoadingCompleteEvent() => OnTutorialLoadingComplete?.Invoke();
@@ -54,6 +54,16 @@ namespace Hyper.Internal
54
54
 
55
55
  #endregion
56
56
 
57
+ #region Restart Flow Settings
58
+
59
+ [Space(20)]
60
+ [Header("Restart Flow Settings")]
61
+ [Tooltip("Enable custom restart flow. If enabled, SDK will fire OnCustomRestart event " +
62
+ "instead of using default restart. Listen to HyperSDK.Event.OnCustomRestart in your game manager.")]
63
+ public bool useCustomRestartFlow = false;
64
+
65
+ #endregion
66
+
57
67
  #region Editor Testing
58
68
  [Header("Editor Simulation")]
59
69
  [Tooltip("Configuration settings for testing within the Unity Editor.")]
@@ -178,6 +178,7 @@ namespace Hyper
178
178
  event Action<bool> OnSoundChanged;
179
179
  event Action OnLivesExhausted;
180
180
  event Action OnHealthExhausted;
181
+ event Action OnCustomRestart;
181
182
  }
182
183
 
183
184
  #region Adapter Implementations
@@ -248,6 +249,7 @@ namespace Hyper
248
249
  private Action<bool> _onSoundChanged;
249
250
  private Action _onLivesExhausted;
250
251
  private Action _onHealthExhausted;
252
+ private Action _onCustomRestart;
251
253
 
252
254
  private Action _gameStartBridge;
253
255
  private Action _timeUpBridge;
@@ -257,6 +259,7 @@ namespace Hyper
257
259
  private Action<bool> _soundChangedBridge;
258
260
  private Action _livesExhaustedBridge;
259
261
  private Action _healthExhaustedBridge;
262
+ private Action _customRestartBridge;
260
263
 
261
264
  public event Action OnGameStart
262
265
  {
@@ -338,6 +341,16 @@ namespace Hyper
338
341
  remove => _onHealthExhausted -= value;
339
342
  }
340
343
 
344
+ public event Action OnCustomRestart
345
+ {
346
+ add
347
+ {
348
+ _onCustomRestart += value;
349
+ RefreshBindings();
350
+ }
351
+ remove => _onCustomRestart -= value;
352
+ }
353
+
341
354
  internal void RefreshBindings()
342
355
  {
343
356
  var manager = HyperRuntime.EventManager;
@@ -366,6 +379,7 @@ namespace Hyper
366
379
  _soundChangedBridge = enabled => _onSoundChanged?.Invoke(enabled);
367
380
  _livesExhaustedBridge = () => _onLivesExhausted?.Invoke();
368
381
  _healthExhaustedBridge = () => _onHealthExhausted?.Invoke();
382
+ _customRestartBridge = () => _onCustomRestart?.Invoke();
369
383
 
370
384
  manager.OnGameStart += _gameStartBridge;
371
385
  manager.OnTimeUp += _timeUpBridge;
@@ -375,6 +389,7 @@ namespace Hyper
375
389
  manager.OnSoundChanged += _soundChangedBridge;
376
390
  manager.OnLivesExhausted += _livesExhaustedBridge;
377
391
  manager.OnHealthExhausted += _healthExhaustedBridge;
392
+ manager.OnCustomRestart += _customRestartBridge;
378
393
 
379
394
  _attachedManager = manager;
380
395
  }
@@ -394,6 +409,7 @@ namespace Hyper
394
409
  if (_soundChangedBridge != null) _attachedManager.OnSoundChanged -= _soundChangedBridge;
395
410
  if (_livesExhaustedBridge != null) _attachedManager.OnLivesExhausted -= _livesExhaustedBridge;
396
411
  if (_healthExhaustedBridge != null) _attachedManager.OnHealthExhausted -= _healthExhaustedBridge;
412
+ if (_customRestartBridge != null) _attachedManager.OnCustomRestart -= _customRestartBridge;
397
413
 
398
414
  _gameStartBridge = null;
399
415
  _timeUpBridge = null;
@@ -403,6 +419,7 @@ namespace Hyper
403
419
  _soundChangedBridge = null;
404
420
  _livesExhaustedBridge = null;
405
421
  _healthExhaustedBridge = null;
422
+ _customRestartBridge = null;
406
423
  _attachedManager = null;
407
424
  }
408
425
  }
@@ -19,6 +19,7 @@ MonoBehaviour:
19
19
  startCTA: 0
20
20
  controlBarLayout: 0
21
21
  controlBarTheme: 1
22
+ useCustomRestartFlow: 0
22
23
  _settings:
23
24
  GameMode: 0
24
25
  ShowInstructions: 0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "app.hypergames.hypersdk",
3
- "version": "1.4.19",
3
+ "version": "1.4.20",
4
4
  "displayName": "HyperSDK",
5
5
  "description": "Official Unity SDK for Hyper: multiplayer battles, leaderboards, deterministic RNG, session management, tutorials, and WebGL optimizations for production-ready games.",
6
6
  "unity": "6000.0",