app.hypergames.hypersdk 1.11.0-beta.1 → 1.11.0-beta.3

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,20 @@
1
+ # [1.11.0-beta.3](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.2...v1.11.0-beta.3) (2026-08-28)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **replay:** reset random state before playback restart ([526a4d9](https://github.com/mvmhyper/hyper-sdk/commit/526a4d98c9b22241e3c52bb6837145bad999fb2b))
7
+ * **sample:** support lane runner custom restart ([49da385](https://github.com/mvmhyper/hyper-sdk/commit/49da385aaa917de438672a8630d4fe7927741b2a))
8
+
9
+ # [1.11.0-beta.2](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.1...v1.11.0-beta.2) (2026-08-27)
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * **replay:** respect custom restart flows ([7470a17](https://github.com/mvmhyper/hyper-sdk/commit/7470a17c60534465500a202c24b0e360f61850fc))
15
+ * **replay:** shorten automatic replay start ([d05dc92](https://github.com/mvmhyper/hyper-sdk/commit/d05dc9267fbf05d392135eac3bb7c4f69b786eff))
16
+ * **timer:** align game time with fixed simulation ([b690d86](https://github.com/mvmhyper/hyper-sdk/commit/b690d861e178f05b21f1a7fbd87e255d97008a8b))
17
+
1
18
  # [1.11.0-beta.1](https://github.com/mvmhyper/hyper-sdk/compare/v1.10.0...v1.11.0-beta.1) (2026-08-26)
2
19
 
3
20
 
@@ -20,6 +20,7 @@ namespace Hyper.Internal
20
20
 
21
21
  private static bool _isInitialized;
22
22
  private static bool _isSoftRestarting;
23
+ private static bool _replayRandomResetPending;
23
24
  private static bool _customLoadingComplete;
24
25
  private static bool _customLoadingActive;
25
26
  private static float _customLoadingProgress;
@@ -118,13 +119,13 @@ namespace Hyper.Internal
118
119
  }
119
120
 
120
121
  /// <summary>
121
- /// Restarts a replay from HyperLoader even when custom restart is enabled.
122
- /// Replay metadata, including the original seed value, remains available to the loader.
122
+ /// Restarts replay playback while preserving its downloaded data and original seed.
123
+ /// Uses the configured custom restart flow when available, otherwise reloads HyperLoader.
123
124
  /// </summary>
124
125
  internal static void RestartReplaySession()
125
126
  {
126
127
  ReplaySessionState.ResetForWatchAgain();
127
- RestartReplayFromLoader();
128
+ RestartReplay();
128
129
  }
129
130
 
130
131
  internal static void SeekReplaySession(float targetProgress, float resumeSpeed, float seekSpeed)
@@ -133,14 +134,26 @@ namespace Hyper.Internal
133
134
 
134
135
  ReplaySessionState.RequestSeek(targetProgress, resumeSpeed, seekSpeed);
135
136
  ReplaySessionState.ResetForSeekRestart();
136
- RestartReplayFromLoader();
137
+ RestartReplay();
137
138
  }
138
139
 
139
- private static void RestartReplayFromLoader()
140
+ private static void RestartReplay()
140
141
  {
141
142
  _isSoftRestarting = true;
142
143
  Time.timeScale = 1f;
143
144
 
145
+ if (_settings != null && _settings.useCustomRestartFlow &&
146
+ _gameManager != null && _eventManager != null)
147
+ {
148
+ _replayManager?.PrepareForRestart();
149
+ // Custom cleanup may use random streams. Rewind after cleanup, immediately before OnGameStart.
150
+ DeferReplayRandomReset();
151
+ _gameManager.ResetUIStateForCustomRestart();
152
+ _eventManager.InvokeCustomRestartEvent();
153
+ _isSoftRestarting = false;
154
+ return;
155
+ }
156
+
144
157
  if (_host != null)
145
158
  {
146
159
  _host.StartCoroutine(RestartSessionCoroutine());
@@ -152,6 +165,32 @@ namespace Hyper.Internal
152
165
  }
153
166
  }
154
167
 
168
+ internal static void ResetReplayRandomState()
169
+ {
170
+ int originalSeed = unchecked((int)ReplaySessionState.OriginalRandomSeed);
171
+ if (HyperRandom.CurrentSeed == originalSeed)
172
+ {
173
+ // Preserve references held by game code while rewinding every stream.
174
+ HyperRandom.ResetAll();
175
+ return;
176
+ }
177
+
178
+ HyperRandom.Init(ReplaySessionState.OriginalRandomSeed);
179
+ }
180
+
181
+ internal static void ApplyPendingReplayRandomReset()
182
+ {
183
+ if (!_replayRandomResetPending) return;
184
+
185
+ _replayRandomResetPending = false;
186
+ ResetReplayRandomState();
187
+ }
188
+
189
+ internal static void DeferReplayRandomReset()
190
+ {
191
+ _replayRandomResetPending = true;
192
+ }
193
+
155
194
  /// <summary>
156
195
  /// Coroutine-based restart that properly unloads all scenes before reloading.
157
196
  /// Handles async scene operations and ensures clean state before restart.
@@ -390,6 +429,7 @@ namespace Hyper.Internal
390
429
  _customLoadingComplete = false;
391
430
  _customLoadingActive = false;
392
431
  _customLoadingProgress = 0f;
432
+ _replayRandomResetPending = false;
393
433
 
394
434
  if (_singletonObject != null)
395
435
  {
@@ -448,6 +488,7 @@ namespace Hyper.Internal
448
488
  _customLoadingComplete = false;
449
489
  _customLoadingActive = false;
450
490
  _customLoadingProgress = 0f;
491
+ _replayRandomResetPending = false;
451
492
  }
452
493
  }
453
494
  }
@@ -1025,6 +1025,8 @@ namespace Hyper.Internal.Managers
1025
1025
  if (_gameStartRequested || _hasGameStarted || _hasGameEnded || !IsInGameScene) return;
1026
1026
  _gameStartRequested = true;
1027
1027
 
1028
+ HyperRuntime.ApplyPendingReplayRandomReset();
1029
+
1028
1030
  HideStartGameDeadlineSnackBar();
1029
1031
  _dataManager.UpdateScore(0);
1030
1032
  HyperRuntime.Timer.StartActiveGameTimer();
@@ -1062,26 +1064,39 @@ namespace Hyper.Internal.Managers
1062
1064
 
1063
1065
  /// <summary>
1064
1066
  /// Resets SDK UI state for custom restart flow.
1065
- /// Called after OnCustomRestart event is fired to prepare the SDK for the developer's restart logic.
1067
+ /// Called before OnCustomRestart so the developer's cleanup starts from reset SDK state.
1066
1068
  /// </summary>
1067
1069
  internal void ResetUIStateForCustomRestart()
1068
1070
  {
1069
1071
  HideGameOverModal();
1070
1072
  HidePauseModals();
1073
+ if (_replayOverModal != null) _replayOverModal.SetActive(false);
1071
1074
 
1072
1075
  // Reset game state flags
1073
1076
  _hasGameStarted = false;
1074
1077
  _gameStartRequested = false;
1075
1078
  _hasGameEnded = false;
1079
+ _replayEndHandled = false;
1080
+ _replayFocusSuspended = false;
1076
1081
  _isPaused = false;
1077
1082
  _isFrozenBeforePause = false;
1078
1083
 
1079
- HyperRuntime.Timer.Reset();
1084
+ HyperRuntime.Timer.ResetForGameRestart();
1080
1085
  HyperRuntime.DataManager.UpdateScore(0);
1081
1086
  HyperRuntime.DataManager.RestoreAudioAfterGameSessionEnd();
1082
1087
 
1083
1088
  ShowControlBarElements();
1084
- ShowStartingInstructionModal();
1089
+ _replayControllerComponent?.ResetForReplayRestart();
1090
+
1091
+ if (IsReplayMode && ReplaySessionState.IsSeeking)
1092
+ {
1093
+ HideStartingInstructionModal();
1094
+ StartCoroutine(StartSeekingReplayWhenReady());
1095
+ }
1096
+ else
1097
+ {
1098
+ ShowStartingInstructionModal();
1099
+ }
1085
1100
  }
1086
1101
 
1087
1102
  #endregion
@@ -39,6 +39,12 @@ namespace Hyper.Internal.Managers
39
39
  ReplaySessionState.SetProgress(_playback.Progress01);
40
40
  }
41
41
 
42
+ internal void PrepareForRestart()
43
+ {
44
+ _endingGame = false;
45
+ _playback?.Stop();
46
+ }
47
+
42
48
  internal void Cleanup()
43
49
  {
44
50
  if (_eventManager != null)
@@ -43,7 +43,7 @@ namespace Hyper.Internal.Managers
43
43
  private bool _isSessionRunning;
44
44
  private bool _sessionWarningTriggered;
45
45
  private bool _timeUpTriggered;
46
- private bool _replayTimeUpPending;
46
+ private bool _timeUpPending;
47
47
 
48
48
  private float _lastUnscaledTime;
49
49
  private bool _hasGameEnded;
@@ -65,7 +65,7 @@ namespace Hyper.Internal.Managers
65
65
  _hasBackendSessionDuration = false;
66
66
  _lastUnscaledTime = Time.unscaledTime;
67
67
  _timeUpTriggered = false;
68
- _replayTimeUpPending = false;
68
+ _timeUpPending = false;
69
69
  }
70
70
 
71
71
  #endregion
@@ -91,27 +91,21 @@ namespace Hyper.Internal.Managers
91
91
  float unscaledDelta = Time.unscaledTime - _lastUnscaledTime;
92
92
  _lastUnscaledTime = Time.unscaledTime;
93
93
 
94
- if (!_gameManager.IsReplayMode)
95
- {
96
- float gameTimerDelta = Mathf.Approximately(Time.timeScale, 0f)
97
- ? 0f
98
- : unscaledDelta;
99
-
100
- UpdatePracticeTimer(gameTimerDelta);
101
- UpdateBattleTimer(gameTimerDelta);
102
- }
103
-
104
94
  UpdateSessionTimer(unscaledDelta);
105
- DispatchPendingReplayTimeUp();
95
+ DispatchPendingTimeUp();
106
96
  }
107
97
 
108
98
  internal void FixedTick()
109
99
  {
110
- if (!_gameManager.IsReplayMode || Mathf.Approximately(Time.timeScale, 0f))
100
+ if (Mathf.Approximately(Time.timeScale, 0f))
111
101
  return;
112
102
 
113
- UpdatePracticeTimer(Time.fixedDeltaTime);
114
- UpdateBattleTimer(Time.fixedDeltaTime, true);
103
+ float gameTimerDelta = _gameManager != null && _gameManager.IsReplayMode
104
+ ? Time.fixedDeltaTime
105
+ : Time.fixedUnscaledDeltaTime;
106
+
107
+ UpdatePracticeTimer(gameTimerDelta);
108
+ UpdateBattleTimer(gameTimerDelta);
115
109
  }
116
110
 
117
111
  public void Reset()
@@ -120,6 +114,19 @@ namespace Hyper.Internal.Managers
120
114
  _lastUnscaledTime = Time.unscaledTime;
121
115
  }
122
116
 
117
+ internal void ResetForGameRestart()
118
+ {
119
+ _practiceTimer = 0f;
120
+ _battleTimer = _gameManager != null ? _gameManager.Config.TimeLimit : 0f;
121
+ _isPracticeRunning = false;
122
+ _isBattleRunning = false;
123
+ _timeUpTriggered = false;
124
+ _timeUpPending = false;
125
+ _hasGameEnded = false;
126
+ _hasGameStarted = false;
127
+ _lastUnscaledTime = Time.unscaledTime;
128
+ }
129
+
123
130
  public void ResumeGameTimersAfterPause()
124
131
  {
125
132
  if (_gameManager.IsBattleMode)
@@ -150,7 +157,7 @@ namespace Hyper.Internal.Managers
150
157
  public void StopAllTimers()
151
158
  {
152
159
  _hasGameEnded = true;
153
- _replayTimeUpPending = false;
160
+ _timeUpPending = false;
154
161
  StopBattle();
155
162
  StopPractice();
156
163
  }
@@ -262,7 +269,7 @@ namespace Hyper.Internal.Managers
262
269
  }
263
270
  }
264
271
 
265
- private void UpdateBattleTimer(float delta, bool deferTimeUp = false)
272
+ private void UpdateBattleTimer(float delta)
266
273
  {
267
274
  if (_isBattleRunning)
268
275
  {
@@ -280,7 +287,7 @@ namespace Hyper.Internal.Managers
280
287
  _battleTimer = 0;
281
288
  if (!_timeUpTriggered)
282
289
  {
283
- TriggerTimeUp(deferTimeUp);
290
+ QueueTimeUp();
284
291
  }
285
292
  }
286
293
  }
@@ -292,30 +299,23 @@ namespace Hyper.Internal.Managers
292
299
 
293
300
  if (_battleTimer <= 0 && !_timeUpTriggered)
294
301
  {
295
- TriggerTimeUp(deferTimeUp);
302
+ QueueTimeUp();
296
303
  }
297
304
  }
298
305
  }
299
306
  }
300
307
 
301
- private void TriggerTimeUp(bool defer)
308
+ private void QueueTimeUp()
302
309
  {
303
- if (defer)
304
- {
305
- _replayTimeUpPending = true;
306
- return;
307
- }
308
-
309
- _timeUpTriggered = true;
310
- _eventManager?.InvokeTimeUpEvent();
310
+ _timeUpPending = true;
311
311
  }
312
312
 
313
- private void DispatchPendingReplayTimeUp()
313
+ private void DispatchPendingTimeUp()
314
314
  {
315
- if (!_replayTimeUpPending)
315
+ if (!_timeUpPending)
316
316
  return;
317
317
 
318
- _replayTimeUpPending = false;
318
+ _timeUpPending = false;
319
319
  if (_hasGameEnded || _timeUpTriggered)
320
320
  return;
321
321
 
@@ -132,6 +132,32 @@ namespace Hyper.Internal
132
132
  if (progressSlider != null) progressSlider.SetValueWithoutNotify(1f);
133
133
  }
134
134
 
135
+ internal void ResetForReplayRestart()
136
+ {
137
+ float playbackSpeed = ReplaySessionState.UserPlaybackSpeed;
138
+ if (!ReplaySessionState.IsSeeking && playbackSpeeds != null && playbackSpeeds.Length > 0)
139
+ {
140
+ playbackSpeed = SanitizePlaybackSpeed(playbackSpeeds[0]);
141
+ ReplaySessionState.SetPlaybackSpeed(playbackSpeed);
142
+ Time.timeScale = playbackSpeed;
143
+ }
144
+
145
+ isCapturingSeek = false;
146
+ pendingSeekTarget = ReplaySessionState.IsSeeking
147
+ ? ReplaySessionState.SeekTarget01
148
+ : 0f;
149
+ wasSeeking = ReplaySessionState.IsSeeking;
150
+
151
+ if (progressSlider != null)
152
+ {
153
+ progressSlider.SetValueWithoutNotify(pendingSeekTarget);
154
+ }
155
+
156
+ UpdatePlaybackSpeedLabel(playbackSpeed);
157
+ AlignPlaybackSpeedIndex(playbackSpeed);
158
+ SetSeekingPresentation(ReplaySessionState.IsSeeking);
159
+ }
160
+
135
161
  private void ExitReplay()
136
162
  {
137
163
  if (exitButton != null) exitButton.interactable = false;
@@ -23,6 +23,13 @@ namespace Hyper.Internal
23
23
  if (exitButton != null) exitButton.onClick.AddListener(Exit);
24
24
  }
25
25
 
26
+ private void OnEnable()
27
+ {
28
+ _handled = false;
29
+ if (watchAgainButton != null) watchAgainButton.interactable = true;
30
+ if (exitButton != null) exitButton.interactable = true;
31
+ }
32
+
26
33
  private void OnDestroy()
27
34
  {
28
35
  if (watchAgainButton != null) watchAgainButton.onClick.RemoveListener(WatchAgain);
@@ -14,7 +14,7 @@ namespace Hyper.Internal
14
14
  [SerializeField] private BlinkingText blinkingText;
15
15
  [SerializeField] private RectTransform swipeGif;
16
16
  [SerializeField] private RectTransform handSpriteInGif;
17
- [SerializeField] private float replayAutoStartDelay = 2f;
17
+ [SerializeField] private float replayAutoStartDelay = 1f;
18
18
  private GameManager _gameManager;
19
19
  private StartCTA _currentCTA;
20
20
  private SwipeDirection _swipeDirection;
@@ -491,7 +491,8 @@ MonoBehaviour:
491
491
  laneChangeSpeed: 14
492
492
  jumpVelocity: 7.5
493
493
  swipeThreshold: 45
494
- startPosition: {x: 3.62, y: 0.567, z: 0}
494
+ startPosition: {x: 3.62, y: 0.5, z: 0}
495
+ groundHeight: 0.5
495
496
  --- !u!54 &554141008
496
497
  Rigidbody:
497
498
  m_ObjectHideFlags: 0
@@ -574,7 +575,7 @@ BoxCollider:
574
575
  m_Material: {fileID: 0}
575
576
  m_IncludeLayers:
576
577
  serializedVersion: 2
577
- m_Bits: 0
578
+ m_Bits: 1
578
579
  m_ExcludeLayers:
579
580
  serializedVersion: 2
580
581
  m_Bits: 0
@@ -1051,7 +1052,7 @@ BoxCollider:
1051
1052
  m_Material: {fileID: 0}
1052
1053
  m_IncludeLayers:
1053
1054
  serializedVersion: 2
1054
- m_Bits: 0
1055
+ m_Bits: 1
1055
1056
  m_ExcludeLayers:
1056
1057
  serializedVersion: 2
1057
1058
  m_Bits: 0
@@ -54,7 +54,7 @@ SphereCollider:
54
54
  m_Material: {fileID: 0}
55
55
  m_IncludeLayers:
56
56
  serializedVersion: 2
57
- m_Bits: 0
57
+ m_Bits: 1
58
58
  m_ExcludeLayers:
59
59
  serializedVersion: 2
60
60
  m_Bits: 0
@@ -54,7 +54,7 @@ BoxCollider:
54
54
  m_Material: {fileID: 0}
55
55
  m_IncludeLayers:
56
56
  serializedVersion: 2
57
- m_Bits: 0
57
+ m_Bits: 1
58
58
  m_ExcludeLayers:
59
59
  serializedVersion: 2
60
60
  m_Bits: 0
@@ -13,13 +13,20 @@ deterministic spawning, a timed score multiplier, and replay integration.
13
13
  Assign `LaneRunnerSample` as the Game and Practice scene in Hyper Game Content
14
14
  Config, then use Hyper's Editor game-mode menu to run Practice, Battle, or Replay.
15
15
  Battle sessions record to `hyper-replay.ndjson` in `Application.persistentDataPath`.
16
+ Enable Custom Restart Flow in Hyper SDK Settings to test in-place Watch Again and
17
+ replay seeking without reloading the scene.
18
+
19
+ The sample uses only Unity's built-in `Default` layer, `Untagged`, and
20
+ `MainCamera`. Its collider overrides and ground safety do not require changes to
21
+ the importing project's tags, layers, or physics collision matrix.
16
22
 
17
23
  ## Integration structure
18
24
 
19
25
  - `LaneRunnerGame` owns rules, score, speed, and power-up state.
20
26
  - `LaneRunnerPlayer` owns physical input and applies commands in `FixedUpdate`.
21
27
  - `LaneRunnerSpawner` creates deterministic rows using `HyperRandom`.
22
- - `LaneRunnerTournamentAdapter` connects score, power-ups, and lifecycle to HyperSDK.
28
+ - `LaneRunnerTournamentAdapter` connects score, power-ups, lifecycle, and custom
29
+ restart handling to HyperSDK.
23
30
  - `LaneRunnerReplayAdapter` records accepted commands and injects replay commands
24
31
  through the same player path.
25
32
 
@@ -11,7 +11,8 @@ namespace HyperSamples.LaneRunner
11
11
  [SerializeField] private float laneChangeSpeed = 14f;
12
12
  [SerializeField] private float jumpVelocity = 7.5f;
13
13
  [SerializeField] private float swipeThreshold = 45f;
14
- [SerializeField] private Vector3 startPosition = new Vector3(0f, 0.68f, 0f);
14
+ [SerializeField] private Vector3 startPosition = new Vector3(0f, 0.5f, 0f);
15
+ [SerializeField] private float groundHeight = 0.5f;
15
16
 
16
17
  public event Action<LaneRunnerCommand> CommandApplied;
17
18
 
@@ -48,18 +49,18 @@ namespace HyperSamples.LaneRunner
48
49
 
49
50
  private void FixedUpdate()
50
51
  {
52
+ StabilizeGround();
53
+
51
54
  if (pendingLaneDelta != 0)
52
55
  {
53
56
  int nextLane = Mathf.Clamp(targetLane + pendingLaneDelta, -1, 1);
54
57
  pendingLaneDelta = 0;
55
- Debug.Log($"LaneRunnerPlayer: Moving from lane {targetLane} to {nextLane}");
56
58
  if (nextLane != targetLane)
57
59
  {
58
60
  LaneRunnerCommand applied = nextLane < targetLane
59
61
  ? LaneRunnerCommand.MoveLeft
60
62
  : LaneRunnerCommand.MoveRight;
61
63
  targetLane = nextLane;
62
- Debug.Log($"targetLane updated to {targetLane}");
63
64
  CommandApplied?.Invoke(applied);
64
65
  }
65
66
  }
@@ -120,7 +121,20 @@ namespace HyperSamples.LaneRunner
120
121
 
121
122
  private bool IsGrounded()
122
123
  {
123
- return body.position.y <= 0.68f && body.linearVelocity.y <= 0.05f;
124
+ return body.position.y <= groundHeight + 0.18f && body.linearVelocity.y <= 0.05f;
125
+ }
126
+
127
+ private void StabilizeGround()
128
+ {
129
+ if (body.position.y >= groundHeight || body.linearVelocity.y > 0f) return;
130
+
131
+ Vector3 position = body.position;
132
+ position.y = groundHeight;
133
+ body.position = position;
134
+
135
+ Vector3 velocity = body.linearVelocity;
136
+ velocity.y = 0f;
137
+ body.linearVelocity = velocity;
124
138
  }
125
139
 
126
140
  private void ReadTouchInput()
@@ -61,7 +61,9 @@ namespace HyperSamples.LaneRunner
61
61
  {
62
62
  for (int i = activeItems.Count - 1; i >= 0; i--)
63
63
  {
64
- if (activeItems[i] != null) Destroy(activeItems[i].gameObject);
64
+ if (activeItems[i] == null) continue;
65
+ activeItems[i].gameObject.SetActive(false);
66
+ Destroy(activeItems[i].gameObject);
65
67
  }
66
68
  activeItems.Clear();
67
69
  }
@@ -16,6 +16,7 @@ namespace HyperSamples.LaneRunner
16
16
  {
17
17
  HyperSDK.Event.OnGameStart += HandleGameStart;
18
18
  HyperSDK.Event.OnGameEnded += HandleGameEnded;
19
+ HyperSDK.Event.OnCustomRestart += HandleCustomRestart;
19
20
  game.ScoreChanged += HandleScoreChanged;
20
21
  game.DoubleScoreChanged += HandleDoubleScoreChanged;
21
22
  game.GameOverRequested += HandleGameOverRequested;
@@ -25,6 +26,7 @@ namespace HyperSamples.LaneRunner
25
26
  {
26
27
  HyperSDK.Event.OnGameStart -= HandleGameStart;
27
28
  HyperSDK.Event.OnGameEnded -= HandleGameEnded;
29
+ HyperSDK.Event.OnCustomRestart -= HandleCustomRestart;
28
30
  game.ScoreChanged -= HandleScoreChanged;
29
31
  game.DoubleScoreChanged -= HandleDoubleScoreChanged;
30
32
  game.GameOverRequested -= HandleGameOverRequested;
@@ -35,6 +37,11 @@ namespace HyperSamples.LaneRunner
35
37
  game.Begin(!HyperSDK.Game.IsReplayMode);
36
38
  }
37
39
 
40
+ private void HandleCustomRestart()
41
+ {
42
+ game.Stop();
43
+ }
44
+
38
45
  private void HandleGameEnded()
39
46
  {
40
47
  game.Stop();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "app.hypergames.hypersdk",
3
- "version": "1.11.0-beta.1",
3
+ "version": "1.11.0-beta.3",
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",