app.hypergames.hypersdk 1.11.0-beta.2 → 1.11.0-beta.21
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 +146 -0
- package/Editor/Scripts/Inspectors/HyperSDKSettingsEditor.cs +6 -0
- package/HyperLoader.unity +2 -2
- package/Runtime/Internal/Core/HyperRuntime.cs +104 -9
- package/Runtime/Internal/Managers/DataManager.cs +2 -1
- package/Runtime/Internal/Managers/EventManager.cs +7 -1
- package/Runtime/Internal/Managers/GameManager.cs +88 -51
- package/Runtime/Internal/Managers/ReplayManager.cs +5 -1
- package/Runtime/Internal/Managers/TimeManager.cs +25 -8
- package/Runtime/Internal/Replay/ReplaySessionState.cs +66 -6
- package/Runtime/Internal/ScriptableObjects/HyperSDKSettings.cs +4 -0
- package/Runtime/Internal/UI/Components/ReplayController.cs +134 -11
- package/Runtime/Internal/UI/Components/ReplaySeekOverlay.cs +18 -0
- package/Runtime/Internal/UI/Components/ReplaySeekOverlay.cs.meta +2 -0
- package/Runtime/Internal/UI/Modals/ReplayPausedModal.cs +145 -0
- package/Runtime/Internal/UI/Modals/ReplayPausedModal.cs.meta +2 -0
- package/Runtime/Internal/UI/Modals/StartingInstructionModal.cs +1 -0
- package/Runtime/Public/Core/HyperSDK.cs +16 -0
- package/Runtime/Public/Replay/ReplayPlaybackEngine.cs +127 -3
- package/Runtime/Resources/Fonts/Nunito/Nunito-Bold SDF.asset +500 -457
- package/Runtime/Resources/Fonts/Wonder Boys/Wonder Boys.asset +394 -379
- package/Runtime/Resources/HyperSDKSettings.asset +1 -0
- package/Runtime/Resources/Sprites/Buttons/Hyper Long White Button_Normal.png +0 -0
- package/Runtime/Resources/Sprites/Buttons/Hyper Long White Button_Normal.png.meta +156 -0
- package/Runtime/Resources/Sprites/Buttons/Hyper Long White Button_Pressed.png +0 -0
- package/Runtime/Resources/Sprites/Buttons/Hyper Long White Button_Pressed.png.meta +156 -0
- package/Runtime/Resources/Sprites/Circle Loader/Property 1=1.png.meta +7 -7
- package/Runtime/Resources/Sprites/Circle Loader/Property 1=2.png.meta +7 -7
- package/Runtime/Resources/Sprites/Circle Loader/Property 1=3.png.meta +7 -7
- package/Runtime/Resources/Sprites/Circle Loader/Property 1=4.png.meta +7 -7
- package/Runtime/Resources/Sprites/Circle Loader/Property 1=5.png.meta +7 -7
- package/Runtime/Resources/Sprites/Replays/Replay.png +0 -0
- package/Runtime/Resources/Sprites/Replays/{Recording.png.meta → Replay.png.meta} +9 -9
- package/Runtime/Resources/UIPrefabs/ControlBar.prefab +5 -5
- package/Runtime/Resources/UIPrefabs/ReplayController.prefab +305 -183
- package/Runtime/Resources/UIPrefabs/ReplayPausedModal.prefab +2194 -0
- package/Runtime/Resources/UIPrefabs/ReplayPausedModal.prefab.meta +7 -0
- package/Runtime/Resources/UIPrefabs/ReplaySeekOverlay.prefab +291 -6
- package/Runtime/Shared/Replay/IReplayPlaybackEngine.cs +3 -0
- package/Samples~/LaneRunner/LaneRunnerSample.unity +4 -3
- package/Samples~/LaneRunner/Prefabs/DoubleScorePickup.prefab +1 -1
- package/Samples~/LaneRunner/Prefabs/Obstacle.prefab +1 -1
- package/Samples~/LaneRunner/README.md +8 -1
- package/Samples~/LaneRunner/Scripts/Gameplay/LaneRunnerPlayer.cs +18 -4
- package/Samples~/LaneRunner/Scripts/Gameplay/LaneRunnerSpawner.cs +3 -1
- package/Samples~/LaneRunner/Scripts/Hyper/LaneRunnerTournamentAdapter.cs +8 -0
- package/package.json +1 -1
- package/Runtime/Resources/Sprites/Replays/Recording.png +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,149 @@
|
|
|
1
|
+
# [1.11.0-beta.21](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.20...v1.11.0-beta.21) (2026-09-03)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **replay:** align gameplay activities to fixed ticks ([1e681b9](https://github.com/mvmhyper/hyper-sdk/commit/1e681b9c7f314a48c417f6e76cb2d4024c890ad3))
|
|
7
|
+
|
|
8
|
+
# [1.11.0-beta.20](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.19...v1.11.0-beta.20) (2026-09-02)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **replay:** separate replay restart configuration ([de01d37](https://github.com/mvmhyper/hyper-sdk/commit/de01d37027fdde5d4f8803fa10e060d48a080316))
|
|
14
|
+
|
|
15
|
+
# [1.11.0-beta.19](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.18...v1.11.0-beta.19) (2026-09-01)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* **replay:** stop seeking at requested progress ([54bf74a](https://github.com/mvmhyper/hyper-sdk/commit/54bf74a4b66b7c19e1398acd611a7d9557ccbcf3))
|
|
21
|
+
|
|
22
|
+
# [1.11.0-beta.18](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.17...v1.11.0-beta.18) (2026-09-01)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Features
|
|
26
|
+
|
|
27
|
+
* **replay:** support custom replay restarts ([bf722ab](https://github.com/mvmhyper/hyper-sdk/commit/bf722abe48add18c356922c60231cb2017e28443))
|
|
28
|
+
|
|
29
|
+
# [1.11.0-beta.17](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.16...v1.11.0-beta.17) (2026-09-01)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
### Features
|
|
33
|
+
|
|
34
|
+
* **replay:** refine seek loading progress ([3d01f94](https://github.com/mvmhyper/hyper-sdk/commit/3d01f94d7e6ce360a61dd3d257149cf7f3237bcb))
|
|
35
|
+
|
|
36
|
+
# [1.11.0-beta.16](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.15...v1.11.0-beta.16) (2026-08-31)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
### Bug Fixes
|
|
40
|
+
|
|
41
|
+
* **replay:** show seek preparation progress ([60213f7](https://github.com/mvmhyper/hyper-sdk/commit/60213f784c5bff39da4634590545fe4d0e4c0911))
|
|
42
|
+
|
|
43
|
+
# [1.11.0-beta.15](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.14...v1.11.0-beta.15) (2026-08-31)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
### Features
|
|
47
|
+
|
|
48
|
+
* **replay:** show seek completion progress ([4e7c1b8](https://github.com/mvmhyper/hyper-sdk/commit/4e7c1b807bd9f34b97477ef39aa9ca3c06316ef3))
|
|
49
|
+
|
|
50
|
+
# [1.11.0-beta.14](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.13...v1.11.0-beta.14) (2026-08-31)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
### Bug Fixes
|
|
54
|
+
|
|
55
|
+
* **replay:** keep seek loader animating ([7e13938](https://github.com/mvmhyper/hyper-sdk/commit/7e13938ce718a238506c08c30744ff24ed7fa710))
|
|
56
|
+
|
|
57
|
+
# [1.11.0-beta.13](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.12...v1.11.0-beta.13) (2026-08-31)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
### Bug Fixes
|
|
61
|
+
|
|
62
|
+
* **replay:** reduce default seek speed to 10x ([ccaf5b9](https://github.com/mvmhyper/hyper-sdk/commit/ccaf5b9807fd9439627072518317ad7f079e544c))
|
|
63
|
+
|
|
64
|
+
# [1.11.0-beta.12](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.11...v1.11.0-beta.12) (2026-08-31)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
### Bug Fixes
|
|
68
|
+
|
|
69
|
+
* **replay:** reduce default seek speed ([d757710](https://github.com/mvmhyper/hyper-sdk/commit/d757710d107a0a496c9d7daa1434004a682bd355))
|
|
70
|
+
|
|
71
|
+
# [1.11.0-beta.11](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.10...v1.11.0-beta.11) (2026-08-30)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
### Bug Fixes
|
|
75
|
+
|
|
76
|
+
* **replay:** apply 30x seek speed on beta ([564769e](https://github.com/mvmhyper/hyper-sdk/commit/564769e4764f27fd301f0e1dc52a4434635f93b7))
|
|
77
|
+
* **replay:** reduce default seek speed ([2cd0a34](https://github.com/mvmhyper/hyper-sdk/commit/2cd0a34c6390725d1c57fc3fa5f691f618c45083))
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
### Features
|
|
81
|
+
|
|
82
|
+
* **replay:** increase default seek speed ([d1a5a46](https://github.com/mvmhyper/hyper-sdk/commit/d1a5a464c1e3e149255bf0d2d183439e9c29cfb3))
|
|
83
|
+
|
|
84
|
+
# [1.11.0-beta.10](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.9...v1.11.0-beta.10) (2026-08-30)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
### Bug Fixes
|
|
88
|
+
|
|
89
|
+
* **replay:** reduce default seek speed ([f70551a](https://github.com/mvmhyper/hyper-sdk/commit/f70551aea942274ace1cb952ddae4e9edb0c1c12))
|
|
90
|
+
|
|
91
|
+
# [1.11.0-beta.9](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.8...v1.11.0-beta.9) (2026-08-30)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
### Bug Fixes
|
|
95
|
+
|
|
96
|
+
* **replay:** show loader while exiting paused replay ([4a2e7a6](https://github.com/mvmhyper/hyper-sdk/commit/4a2e7a6045017ea8ed3ae3525271440dbf013e6c))
|
|
97
|
+
|
|
98
|
+
# [1.11.0-beta.8](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.7...v1.11.0-beta.8) (2026-08-30)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
### Bug Fixes
|
|
102
|
+
|
|
103
|
+
* **replay:** mute audio while seeking ([5ab8cd1](https://github.com/mvmhyper/hyper-sdk/commit/5ab8cd1411493cb5add07b51dc190c85251f99d2))
|
|
104
|
+
|
|
105
|
+
# [1.11.0-beta.7](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.6...v1.11.0-beta.7) (2026-08-30)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
### Bug Fixes
|
|
109
|
+
|
|
110
|
+
* **replay:** stabilize scene reload seeking ([dd9ac63](https://github.com/mvmhyper/hyper-sdk/commit/dd9ac632d08349d9578f64ae0b2dc2ab905a26af))
|
|
111
|
+
|
|
112
|
+
# [1.11.0-beta.6](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.5...v1.11.0-beta.6) (2026-08-29)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
### Bug Fixes
|
|
116
|
+
|
|
117
|
+
* **timer:** restore gameplay timers after pause ([ca82d57](https://github.com/mvmhyper/hyper-sdk/commit/ca82d57df87618807cbae611c0a9d6acc14f8470))
|
|
118
|
+
|
|
119
|
+
# [1.11.0-beta.5](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.4...v1.11.0-beta.5) (2026-08-28)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
### Bug Fixes
|
|
123
|
+
|
|
124
|
+
* **replay:** wait for custom restart readiness ([43f1aeb](https://github.com/mvmhyper/hyper-sdk/commit/43f1aeb6a127c8c12dbb8379e7230d64ef5e0763))
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
### Features
|
|
128
|
+
|
|
129
|
+
* **replay:** add replay pause controls ([b9fb470](https://github.com/mvmhyper/hyper-sdk/commit/b9fb470e65c69e66a8a9611b0caa7e5417b1e4bf))
|
|
130
|
+
* **replay:** update replay control bar assets ([79ce8c0](https://github.com/mvmhyper/hyper-sdk/commit/79ce8c0f1b68129ae5b8bcf18a302117cf11c885))
|
|
131
|
+
|
|
132
|
+
# [1.11.0-beta.4](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.3...v1.11.0-beta.4) (2026-08-28)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
### Bug Fixes
|
|
136
|
+
|
|
137
|
+
* **replay:** align recording with fixed simulation ([ae2b322](https://github.com/mvmhyper/hyper-sdk/commit/ae2b32216a0a9ea125572d788eee3bfd846414b0))
|
|
138
|
+
|
|
139
|
+
# [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)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
### Bug Fixes
|
|
143
|
+
|
|
144
|
+
* **replay:** reset random state before playback restart ([526a4d9](https://github.com/mvmhyper/hyper-sdk/commit/526a4d98c9b22241e3c52bb6837145bad999fb2b))
|
|
145
|
+
* **sample:** support lane runner custom restart ([49da385](https://github.com/mvmhyper/hyper-sdk/commit/49da385aaa917de438672a8630d4fe7927741b2a))
|
|
146
|
+
|
|
1
147
|
# [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)
|
|
2
148
|
|
|
3
149
|
|
|
@@ -170,6 +170,12 @@ namespace Hyper.Editor
|
|
|
170
170
|
settings.useCustomRestartFlow = EditorGUILayout.Toggle(
|
|
171
171
|
new GUIContent("Use Custom Restart Flow"),
|
|
172
172
|
settings.useCustomRestartFlow);
|
|
173
|
+
settings.useCustomReplayRestartFlow = EditorGUILayout.Toggle(
|
|
174
|
+
new GUIContent(
|
|
175
|
+
"Use Custom Replay Restart Flow",
|
|
176
|
+
"Use game-owned restart logic for replay Watch Again and seeking. " +
|
|
177
|
+
"Disabled uses HyperLoader to rebuild deterministic game state."),
|
|
178
|
+
settings.useCustomReplayRestartFlow);
|
|
173
179
|
|
|
174
180
|
EditorGUILayout.Space(12);
|
|
175
181
|
// Draw Editor Testing
|
package/HyperLoader.unity
CHANGED
|
@@ -304,7 +304,7 @@ RectTransform:
|
|
|
304
304
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
305
305
|
m_AnchorMin: {x: 0, y: 1}
|
|
306
306
|
m_AnchorMax: {x: 0, y: 1}
|
|
307
|
-
m_AnchoredPosition: {x: 489.
|
|
307
|
+
m_AnchoredPosition: {x: 489.20746, y: -280.1698}
|
|
308
308
|
m_SizeDelta: {x: 1044.9, y: 239.347}
|
|
309
309
|
m_Pivot: {x: 0.5, y: 0.5}
|
|
310
310
|
--- !u!114 &751153944
|
|
@@ -1092,7 +1092,7 @@ RectTransform:
|
|
|
1092
1092
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
1093
1093
|
m_AnchorMin: {x: 0, y: 1}
|
|
1094
1094
|
m_AnchorMax: {x: 0, y: 1}
|
|
1095
|
-
m_AnchoredPosition: {x: 489.
|
|
1095
|
+
m_AnchoredPosition: {x: 489.20746, y: -133.2274}
|
|
1096
1096
|
m_SizeDelta: {x: 875, y: 54.5378}
|
|
1097
1097
|
m_Pivot: {x: 0.5, y: 0.5}
|
|
1098
1098
|
--- !u!1 &2874543288936963705
|
|
@@ -15,11 +15,16 @@ namespace Hyper.Internal
|
|
|
15
15
|
/// </summary>
|
|
16
16
|
internal static class HyperRuntime
|
|
17
17
|
{
|
|
18
|
+
private const float ReplayCustomRestartTimeoutSeconds = 10f;
|
|
19
|
+
|
|
18
20
|
private static HyperRuntimeHost _host;
|
|
19
21
|
private static GameObject _singletonObject;
|
|
20
22
|
|
|
21
23
|
private static bool _isInitialized;
|
|
22
24
|
private static bool _isSoftRestarting;
|
|
25
|
+
private static bool _replayRandomResetPending;
|
|
26
|
+
private static bool _replayCustomRestartPending;
|
|
27
|
+
private static int _replayCustomRestartVersion;
|
|
23
28
|
private static bool _customLoadingComplete;
|
|
24
29
|
private static bool _customLoadingActive;
|
|
25
30
|
private static float _customLoadingProgress;
|
|
@@ -32,6 +37,7 @@ namespace Hyper.Internal
|
|
|
32
37
|
private static EventManager _eventManager;
|
|
33
38
|
private static TimerManager _timerManager;
|
|
34
39
|
private static ReplayManager _replayManager;
|
|
40
|
+
private static double _fixedSimulationTimeSeconds;
|
|
35
41
|
|
|
36
42
|
internal static bool IsInitialized => _isInitialized;
|
|
37
43
|
internal static bool IsSoftRestarting
|
|
@@ -39,6 +45,7 @@ namespace Hyper.Internal
|
|
|
39
45
|
get => _isSoftRestarting;
|
|
40
46
|
set => _isSoftRestarting = value;
|
|
41
47
|
}
|
|
48
|
+
internal static bool IsReplayCustomRestartPending => _replayCustomRestartPending;
|
|
42
49
|
internal static bool CustomLoadingComplete
|
|
43
50
|
{
|
|
44
51
|
get => _customLoadingComplete;
|
|
@@ -58,6 +65,7 @@ namespace Hyper.Internal
|
|
|
58
65
|
internal static EventManager EventManager => _eventManager;
|
|
59
66
|
internal static TimerManager Timer => _timerManager;
|
|
60
67
|
internal static ReplayManager ReplayManager => _replayManager;
|
|
68
|
+
internal static double FixedSimulationTimeSeconds => _fixedSimulationTimeSeconds;
|
|
61
69
|
|
|
62
70
|
internal static event Action CustomLoadingStarted
|
|
63
71
|
{
|
|
@@ -118,8 +126,8 @@ namespace Hyper.Internal
|
|
|
118
126
|
}
|
|
119
127
|
|
|
120
128
|
/// <summary>
|
|
121
|
-
/// Restarts replay playback while preserving
|
|
122
|
-
///
|
|
129
|
+
/// Restarts replay playback while preserving replay session data. Uses the game-owned
|
|
130
|
+
/// replay restart flow only when explicitly enabled and otherwise reloads HyperLoader.
|
|
123
131
|
/// </summary>
|
|
124
132
|
internal static void RestartReplaySession()
|
|
125
133
|
{
|
|
@@ -141,17 +149,66 @@ namespace Hyper.Internal
|
|
|
141
149
|
_isSoftRestarting = true;
|
|
142
150
|
Time.timeScale = 1f;
|
|
143
151
|
|
|
144
|
-
|
|
145
|
-
|
|
152
|
+
_replayCustomRestartPending = false;
|
|
153
|
+
_replayRandomResetPending = false;
|
|
154
|
+
int restartVersion = ++_replayCustomRestartVersion;
|
|
155
|
+
_replayManager?.PrepareForRestart();
|
|
156
|
+
|
|
157
|
+
if (_settings != null && _settings.useCustomReplayRestartFlow &&
|
|
158
|
+
_host != null && _gameManager != null && _eventManager != null)
|
|
146
159
|
{
|
|
147
|
-
|
|
148
|
-
|
|
160
|
+
_replayCustomRestartPending = true;
|
|
161
|
+
_replayRandomResetPending = true;
|
|
149
162
|
_gameManager.ResetUIStateForCustomRestart();
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
163
|
+
|
|
164
|
+
try
|
|
165
|
+
{
|
|
166
|
+
if (!_eventManager.InvokeCustomRestartEvent())
|
|
167
|
+
{
|
|
168
|
+
HyperDebug.LogWarning(
|
|
169
|
+
"[Replay] Custom restart has no handler; falling back to HyperLoader.");
|
|
170
|
+
BeginReplaySceneRestart(restartVersion);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
_host.StartCoroutine(WaitForReplayCustomRestart(restartVersion));
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
catch (Exception exception)
|
|
178
|
+
{
|
|
179
|
+
HyperDebug.LogWarning(
|
|
180
|
+
$"[Replay] Custom restart failed; falling back to HyperLoader: {exception.Message}");
|
|
181
|
+
BeginReplaySceneRestart(restartVersion);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
153
184
|
}
|
|
154
185
|
|
|
186
|
+
BeginReplaySceneRestart(restartVersion);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
private static IEnumerator WaitForReplayCustomRestart(int restartVersion)
|
|
190
|
+
{
|
|
191
|
+
float timeoutAt = Time.realtimeSinceStartup + ReplayCustomRestartTimeoutSeconds;
|
|
192
|
+
while (_replayCustomRestartPending && restartVersion == _replayCustomRestartVersion &&
|
|
193
|
+
Time.realtimeSinceStartup < timeoutAt)
|
|
194
|
+
{
|
|
195
|
+
yield return null;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (!_replayCustomRestartPending || restartVersion != _replayCustomRestartVersion) yield break;
|
|
199
|
+
|
|
200
|
+
HyperDebug.LogWarning(
|
|
201
|
+
$"[Replay] Custom restart did not complete within {ReplayCustomRestartTimeoutSeconds:0} seconds; " +
|
|
202
|
+
"falling back to HyperLoader.");
|
|
203
|
+
BeginReplaySceneRestart(restartVersion);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
private static void BeginReplaySceneRestart(int restartVersion)
|
|
207
|
+
{
|
|
208
|
+
if (restartVersion != _replayCustomRestartVersion) return;
|
|
209
|
+
|
|
210
|
+
_replayCustomRestartPending = false;
|
|
211
|
+
_replayRandomResetPending = false;
|
|
155
212
|
if (_host != null)
|
|
156
213
|
{
|
|
157
214
|
_host.StartCoroutine(RestartSessionCoroutine());
|
|
@@ -176,6 +233,34 @@ namespace Hyper.Internal
|
|
|
176
233
|
HyperRandom.Init(ReplaySessionState.OriginalRandomSeed);
|
|
177
234
|
}
|
|
178
235
|
|
|
236
|
+
internal static void ApplyPendingReplayRandomReset()
|
|
237
|
+
{
|
|
238
|
+
if (!_replayRandomResetPending) return;
|
|
239
|
+
|
|
240
|
+
_replayRandomResetPending = false;
|
|
241
|
+
ResetReplayRandomState();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
internal static void DeferReplayRandomReset()
|
|
245
|
+
{
|
|
246
|
+
_replayRandomResetPending = true;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
internal static void CompleteCustomRestart()
|
|
250
|
+
{
|
|
251
|
+
if (!_replayCustomRestartPending || _host == null) return;
|
|
252
|
+
|
|
253
|
+
_replayCustomRestartPending = false;
|
|
254
|
+
_host.StartCoroutine(CompleteReplayCustomRestartNextFrame());
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
private static IEnumerator CompleteReplayCustomRestartNextFrame()
|
|
258
|
+
{
|
|
259
|
+
yield return null;
|
|
260
|
+
_gameManager?.CompleteReplayCustomRestart();
|
|
261
|
+
_isSoftRestarting = false;
|
|
262
|
+
}
|
|
263
|
+
|
|
179
264
|
/// <summary>
|
|
180
265
|
/// Coroutine-based restart that properly unloads all scenes before reloading.
|
|
181
266
|
/// Handles async scene operations and ensures clean state before restart.
|
|
@@ -184,6 +269,7 @@ namespace Hyper.Internal
|
|
|
184
269
|
{
|
|
185
270
|
yield return UnloadAllScenesCoroutine();
|
|
186
271
|
|
|
272
|
+
Clear();
|
|
187
273
|
ClearAllDontDestroyOnLoadObjects();
|
|
188
274
|
SceneManager.LoadScene("HyperLoader");
|
|
189
275
|
}
|
|
@@ -381,6 +467,7 @@ namespace Hyper.Internal
|
|
|
381
467
|
internal static void FixedTick()
|
|
382
468
|
{
|
|
383
469
|
if (!_isInitialized) return;
|
|
470
|
+
_fixedSimulationTimeSeconds += Time.fixedDeltaTime;
|
|
384
471
|
_replayManager?.FixedTick();
|
|
385
472
|
_timerManager?.FixedTick();
|
|
386
473
|
}
|
|
@@ -414,6 +501,10 @@ namespace Hyper.Internal
|
|
|
414
501
|
_customLoadingComplete = false;
|
|
415
502
|
_customLoadingActive = false;
|
|
416
503
|
_customLoadingProgress = 0f;
|
|
504
|
+
_replayRandomResetPending = false;
|
|
505
|
+
_replayCustomRestartPending = false;
|
|
506
|
+
_replayCustomRestartVersion++;
|
|
507
|
+
_fixedSimulationTimeSeconds = 0d;
|
|
417
508
|
|
|
418
509
|
if (_singletonObject != null)
|
|
419
510
|
{
|
|
@@ -472,6 +563,10 @@ namespace Hyper.Internal
|
|
|
472
563
|
_customLoadingComplete = false;
|
|
473
564
|
_customLoadingActive = false;
|
|
474
565
|
_customLoadingProgress = 0f;
|
|
566
|
+
_replayRandomResetPending = false;
|
|
567
|
+
_replayCustomRestartPending = false;
|
|
568
|
+
_replayCustomRestartVersion++;
|
|
569
|
+
_fixedSimulationTimeSeconds = 0d;
|
|
475
570
|
}
|
|
476
571
|
}
|
|
477
572
|
}
|
|
@@ -219,6 +219,7 @@ namespace Hyper.Internal.Managers
|
|
|
219
219
|
internal void ConfigurePlayerSoundSetting()
|
|
220
220
|
{
|
|
221
221
|
SetSound(GetSound());
|
|
222
|
+
ReplaySessionState.EnsureAudioMutedDuringSeek();
|
|
222
223
|
if (_gameManager == null) _gameManager = HyperRuntime.GameManager;
|
|
223
224
|
}
|
|
224
225
|
|
|
@@ -462,7 +463,7 @@ namespace Hyper.Internal.Managers
|
|
|
462
463
|
|
|
463
464
|
private static double GetSimulationTimeSeconds()
|
|
464
465
|
{
|
|
465
|
-
return
|
|
466
|
+
return HyperRuntime.FixedSimulationTimeSeconds;
|
|
466
467
|
}
|
|
467
468
|
|
|
468
469
|
private ScoreData GetPooledScoreData()
|
|
@@ -79,7 +79,13 @@ namespace Hyper.Internal.Managers
|
|
|
79
79
|
internal void InvokeGameEndedEvent() => OnGameEnded?.Invoke();
|
|
80
80
|
internal void InvokeLivesExhaustedEvent() => OnLivesExhausted?.Invoke();
|
|
81
81
|
internal void InvokeHealthExhaustedEvent() => OnHealthExhausted?.Invoke();
|
|
82
|
-
internal
|
|
82
|
+
internal bool InvokeCustomRestartEvent()
|
|
83
|
+
{
|
|
84
|
+
Action handler = OnCustomRestart;
|
|
85
|
+
if (handler == null) return false;
|
|
86
|
+
handler.Invoke();
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
83
89
|
internal void InvokeConnectionLostEvent() => OnInternetConnectionLost?.Invoke();
|
|
84
90
|
internal void InvokeConnectionFoundEvent() => OnInternetConnectionFound?.Invoke();
|
|
85
91
|
internal void InvokeBackendSocketManuallyClosedEvent() => OnBackendSocketManuallyClosed?.Invoke();
|
|
@@ -191,6 +191,41 @@ namespace Hyper.Internal.Managers
|
|
|
191
191
|
Resources.UnloadUnusedAssets();
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
+
internal void PauseReplay()
|
|
195
|
+
{
|
|
196
|
+
if (!IsReplayMode || !_hasGameStarted || _isPaused || _hasGameEnded)
|
|
197
|
+
{
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
_isPaused = true;
|
|
202
|
+
_savedReplayTimeScale = Time.timeScale > 0f
|
|
203
|
+
? Time.timeScale
|
|
204
|
+
: ReplaySessionState.PlaybackSpeed;
|
|
205
|
+
Time.timeScale = 0f;
|
|
206
|
+
HyperRuntime.Timer.PauseGameplayTimers();
|
|
207
|
+
|
|
208
|
+
_previousTimeScale = 0f;
|
|
209
|
+
_eventManager.InvokeTimeScaleFrozenEvent();
|
|
210
|
+
ReplayPresentationCanvas.SetSeekingLayer(false);
|
|
211
|
+
SetBlockerActive(true);
|
|
212
|
+
ShowReplayPauseModal();
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
internal void ResumeReplay()
|
|
216
|
+
{
|
|
217
|
+
if (!IsReplayMode || !_isPaused || _hasGameEnded) return;
|
|
218
|
+
|
|
219
|
+
_isPaused = false;
|
|
220
|
+
HidePauseModals();
|
|
221
|
+
Time.timeScale = _savedReplayTimeScale > 0f ? _savedReplayTimeScale : 1f;
|
|
222
|
+
HyperRuntime.Timer.ResumeGameTimersAfterPause();
|
|
223
|
+
|
|
224
|
+
_previousTimeScale = Time.timeScale;
|
|
225
|
+
_eventManager.InvokeTimeScaleResumedEvent();
|
|
226
|
+
ReplayPresentationCanvas.SetSeekingLayer(ReplaySessionState.IsSeeking);
|
|
227
|
+
}
|
|
228
|
+
|
|
194
229
|
internal void ResumeGame()
|
|
195
230
|
{
|
|
196
231
|
_isPaused = false;
|
|
@@ -222,51 +257,7 @@ namespace Hyper.Internal.Managers
|
|
|
222
257
|
private void HandleReplayFocus(bool hasFocus)
|
|
223
258
|
{
|
|
224
259
|
if (!_hasGameStarted || _hasGameEnded) return;
|
|
225
|
-
|
|
226
|
-
if (!hasFocus && _replayFocusResumeCoroutine != null)
|
|
227
|
-
{
|
|
228
|
-
StopCoroutine(_replayFocusResumeCoroutine);
|
|
229
|
-
_replayFocusResumeCoroutine = null;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
if (!hasFocus && !_replayFocusSuspended)
|
|
233
|
-
{
|
|
234
|
-
_replayFocusSuspended = true;
|
|
235
|
-
_savedReplayTimeScale = Time.timeScale;
|
|
236
|
-
Time.timeScale = 0f;
|
|
237
|
-
HyperRuntime.Timer.PauseGameplayTimers();
|
|
238
|
-
|
|
239
|
-
// WebGL may stop producing frames immediately after focus loss,
|
|
240
|
-
// so suspend replay timing here instead of waiting for Update.
|
|
241
|
-
_previousTimeScale = 0f;
|
|
242
|
-
_eventManager.InvokeTimeScaleFrozenEvent();
|
|
243
|
-
HyperDebug.Log("Time scale frozen event invoked");
|
|
244
|
-
}
|
|
245
|
-
else if (hasFocus && _replayFocusSuspended)
|
|
246
|
-
{
|
|
247
|
-
if (_replayFocusResumeCoroutine == null)
|
|
248
|
-
{
|
|
249
|
-
_replayFocusResumeCoroutine = StartCoroutine(ResumeReplayAfterFocus());
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
private IEnumerator ResumeReplayAfterFocus()
|
|
255
|
-
{
|
|
256
|
-
// WebGL reports focus before Unity refreshes its unscaled clock. Keep
|
|
257
|
-
// gameplay and replay frozen briefly while session time continues.
|
|
258
|
-
yield return new WaitForSecondsRealtime(1f);
|
|
259
|
-
|
|
260
|
-
_replayFocusResumeCoroutine = null;
|
|
261
|
-
if (!_replayFocusSuspended || _hasGameEnded) yield break;
|
|
262
|
-
|
|
263
|
-
_replayFocusSuspended = false;
|
|
264
|
-
Time.timeScale = _savedReplayTimeScale > 0f ? _savedReplayTimeScale : 1f;
|
|
265
|
-
HyperRuntime.Timer.ResumeGameTimersAfterPause();
|
|
266
|
-
|
|
267
|
-
_previousTimeScale = Time.timeScale;
|
|
268
|
-
_eventManager.InvokeTimeScaleResumedEvent();
|
|
269
|
-
HyperDebug.Log("Time scale resumed event invoked");
|
|
260
|
+
if (!hasFocus) PauseReplay();
|
|
270
261
|
}
|
|
271
262
|
|
|
272
263
|
void HandlePauseState(bool shouldPause)
|
|
@@ -552,7 +543,7 @@ namespace Hyper.Internal.Managers
|
|
|
552
543
|
|
|
553
544
|
internal void ShowStartGameDeadline(int timeLeft)
|
|
554
545
|
{
|
|
555
|
-
if (_hasGameStarted || !IsInGameScene) return;
|
|
546
|
+
if (_hasGameStarted || !IsInGameScene || IsReplayMode) return;
|
|
556
547
|
|
|
557
548
|
EnsureStartGameDeadlineBar();
|
|
558
549
|
_eventManager.OnSessionAboutToExpire += ChangeDeadlineColorToRed;
|
|
@@ -728,7 +719,6 @@ namespace Hyper.Internal.Managers
|
|
|
728
719
|
private bool _isPortrait;
|
|
729
720
|
private float _previousTimeScale = 1f;
|
|
730
721
|
private float _savedTimeScaleBeforePause = 1f;
|
|
731
|
-
private bool _replayFocusSuspended;
|
|
732
722
|
private float _savedReplayTimeScale = 1f;
|
|
733
723
|
|
|
734
724
|
#endregion
|
|
@@ -1025,6 +1015,8 @@ namespace Hyper.Internal.Managers
|
|
|
1025
1015
|
if (_gameStartRequested || _hasGameStarted || _hasGameEnded || !IsInGameScene) return;
|
|
1026
1016
|
_gameStartRequested = true;
|
|
1027
1017
|
|
|
1018
|
+
HyperRuntime.ApplyPendingReplayRandomReset();
|
|
1019
|
+
|
|
1028
1020
|
HideStartGameDeadlineSnackBar();
|
|
1029
1021
|
_dataManager.UpdateScore(0);
|
|
1030
1022
|
HyperRuntime.Timer.StartActiveGameTimer();
|
|
@@ -1062,7 +1054,7 @@ namespace Hyper.Internal.Managers
|
|
|
1062
1054
|
|
|
1063
1055
|
/// <summary>
|
|
1064
1056
|
/// Resets SDK UI state for custom restart flow.
|
|
1065
|
-
/// Called
|
|
1057
|
+
/// Called before OnCustomRestart so the developer's cleanup starts from reset SDK state.
|
|
1066
1058
|
/// </summary>
|
|
1067
1059
|
internal void ResetUIStateForCustomRestart()
|
|
1068
1060
|
{
|
|
@@ -1075,7 +1067,6 @@ namespace Hyper.Internal.Managers
|
|
|
1075
1067
|
_gameStartRequested = false;
|
|
1076
1068
|
_hasGameEnded = false;
|
|
1077
1069
|
_replayEndHandled = false;
|
|
1078
|
-
_replayFocusSuspended = false;
|
|
1079
1070
|
_isPaused = false;
|
|
1080
1071
|
_isFrozenBeforePause = false;
|
|
1081
1072
|
|
|
@@ -1086,6 +1077,12 @@ namespace Hyper.Internal.Managers
|
|
|
1086
1077
|
ShowControlBarElements();
|
|
1087
1078
|
_replayControllerComponent?.ResetForReplayRestart();
|
|
1088
1079
|
|
|
1080
|
+
if (IsReplayMode && HyperRuntime.IsReplayCustomRestartPending)
|
|
1081
|
+
{
|
|
1082
|
+
HideStartingInstructionModal();
|
|
1083
|
+
return;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1089
1086
|
if (IsReplayMode && ReplaySessionState.IsSeeking)
|
|
1090
1087
|
{
|
|
1091
1088
|
HideStartingInstructionModal();
|
|
@@ -1097,6 +1094,20 @@ namespace Hyper.Internal.Managers
|
|
|
1097
1094
|
}
|
|
1098
1095
|
}
|
|
1099
1096
|
|
|
1097
|
+
internal void CompleteReplayCustomRestart()
|
|
1098
|
+
{
|
|
1099
|
+
if (!IsReplayMode || _gameStartRequested || _hasGameStarted || _hasGameEnded) return;
|
|
1100
|
+
|
|
1101
|
+
if (ReplaySessionState.IsSeeking)
|
|
1102
|
+
{
|
|
1103
|
+
StartCoroutine(StartSeekingReplayWhenReady());
|
|
1104
|
+
}
|
|
1105
|
+
else
|
|
1106
|
+
{
|
|
1107
|
+
ShowStartingInstructionModal();
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1100
1111
|
#endregion
|
|
1101
1112
|
|
|
1102
1113
|
#region Game End Logic
|
|
@@ -1138,7 +1149,6 @@ namespace Hyper.Internal.Managers
|
|
|
1138
1149
|
|
|
1139
1150
|
_replayEndHandled = true;
|
|
1140
1151
|
_hasGameEnded = true;
|
|
1141
|
-
_replayFocusSuspended = false;
|
|
1142
1152
|
Time.timeScale = 1f;
|
|
1143
1153
|
_eventManager.InvokeGameEndedEvent();
|
|
1144
1154
|
HyperRuntime.Timer.StopAllTimers();
|
|
@@ -1160,10 +1170,12 @@ namespace Hyper.Internal.Managers
|
|
|
1160
1170
|
_eventManager.InvokeGameEndedEvent();
|
|
1161
1171
|
}
|
|
1162
1172
|
|
|
1173
|
+
_isPaused = false;
|
|
1163
1174
|
Time.timeScale = 1f;
|
|
1164
1175
|
HyperRuntime.Timer.StopAllTimers();
|
|
1165
1176
|
_dataManager.StopCapturingScores();
|
|
1166
1177
|
HyperRuntime.BackendManager.StopSendingScores();
|
|
1178
|
+
HidePauseModals();
|
|
1167
1179
|
_replayControllerComponent?.SetReplayEnded();
|
|
1168
1180
|
ReplaySessionState.Clear();
|
|
1169
1181
|
ReplayPresentationCanvas.DestroyCurrent();
|
|
@@ -1274,8 +1286,8 @@ namespace Hyper.Internal.Managers
|
|
|
1274
1286
|
private GameObject _replayControllerObject;
|
|
1275
1287
|
private ReplayController _replayControllerComponent;
|
|
1276
1288
|
private GameObject _replayOverModal;
|
|
1289
|
+
private GameObject _replayPausedModal;
|
|
1277
1290
|
private Coroutine _replayConnectionCheckCoroutine;
|
|
1278
|
-
private Coroutine _replayFocusResumeCoroutine;
|
|
1279
1291
|
|
|
1280
1292
|
private GameObject _connectionStatusBar;
|
|
1281
1293
|
private GameObject _startGameDeadlineStatusBar;
|
|
@@ -1505,6 +1517,30 @@ namespace Hyper.Internal.Managers
|
|
|
1505
1517
|
_replayOverModal.transform.SetAsLastSibling();
|
|
1506
1518
|
}
|
|
1507
1519
|
|
|
1520
|
+
private void ShowReplayPauseModal()
|
|
1521
|
+
{
|
|
1522
|
+
if (_replayPausedModal == null)
|
|
1523
|
+
{
|
|
1524
|
+
if (_canvas == null) CreateCanvas();
|
|
1525
|
+
GameObject prefab = Resources.Load<GameObject>("UIPrefabs/ReplayPausedModal");
|
|
1526
|
+
if (prefab == null)
|
|
1527
|
+
{
|
|
1528
|
+
HyperDebug.LogWarning("[GameManager] ReplayPausedModal prefab not found.");
|
|
1529
|
+
ResumeReplay();
|
|
1530
|
+
return;
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
_replayPausedModal = InstantiateModal(prefab);
|
|
1534
|
+
if (_replayPausedModal.GetComponent<ReplayPausedModal>() == null)
|
|
1535
|
+
{
|
|
1536
|
+
_replayPausedModal.AddComponent<ReplayPausedModal>();
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
_replayPausedModal.SetActive(true);
|
|
1541
|
+
_replayPausedModal.transform.SetAsLastSibling();
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1508
1544
|
private void EnsureConnectionStatusBar()
|
|
1509
1545
|
{
|
|
1510
1546
|
if (_connectionStatusBar != null) return;
|
|
@@ -1753,6 +1789,7 @@ namespace Hyper.Internal.Managers
|
|
|
1753
1789
|
internal void HidePauseModals()
|
|
1754
1790
|
{
|
|
1755
1791
|
SetBlockerActive(false);
|
|
1792
|
+
if (_replayPausedModal != null) _replayPausedModal.SetActive(false);
|
|
1756
1793
|
if (_battleGamePausedModal != null) _battleGamePausedModal.SetActive(false);
|
|
1757
1794
|
if (_practicePausedModal != null) _practicePausedModal.SetActive(false);
|
|
1758
1795
|
if (_battleGamePausedLandscapeModal != null) _battleGamePausedLandscapeModal.SetActive(false);
|
|
@@ -36,7 +36,10 @@ namespace Hyper.Internal.Managers
|
|
|
36
36
|
{
|
|
37
37
|
if (_playback == null || !_playback.IsPlaying) return;
|
|
38
38
|
_playback.Tick();
|
|
39
|
-
ReplaySessionState.SetProgress(_playback.Progress01)
|
|
39
|
+
if (ReplaySessionState.SetProgress(_playback.Progress01))
|
|
40
|
+
{
|
|
41
|
+
UnityEngine.Time.timeScale = ReplaySessionState.PlaybackSpeed;
|
|
42
|
+
}
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
internal void PrepareForRestart()
|
|
@@ -74,6 +77,7 @@ namespace Hyper.Internal.Managers
|
|
|
74
77
|
}
|
|
75
78
|
|
|
76
79
|
_playback.Begin(ReplaySessionState.ReplayNdjson);
|
|
80
|
+
ReplaySessionState.SetGameplayStartProgress(_playback.GameplayStartProgress01);
|
|
77
81
|
}
|
|
78
82
|
|
|
79
83
|
private void HandleGameEnded()
|