app.hypergames.hypersdk 1.11.0-beta.8 → 1.11.0
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 +188 -0
- package/Editor/Scripts/Inspectors/HyperSDKSettingsEditor.cs +15 -0
- package/HyperLoader.unity +2 -2
- package/Runtime/Internal/Bootstrap/HyperLoader.cs +5 -1
- package/Runtime/Internal/Core/HyperRuntime.cs +63 -1
- package/Runtime/Internal/Managers/BackendManager.cs +26 -3
- package/Runtime/Internal/Managers/DataManager.cs +8 -0
- package/Runtime/Internal/Managers/EventManager.cs +7 -1
- package/Runtime/Internal/Managers/GameManager.cs +1 -1
- package/Runtime/Internal/Managers/ReplayManager.cs +4 -1
- package/Runtime/Internal/Managers/TimeManager.cs +21 -6
- package/Runtime/Internal/Replay/ReplaySessionState.cs +15 -4
- package/Runtime/Internal/ScriptableObjects/HyperSDKSettings.cs +10 -0
- package/Runtime/Internal/UI/Components/ReplayController.cs +205 -27
- package/Runtime/Internal/UI/Components/ReplayPresentationCanvas.cs +1 -1
- 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 +12 -1
- package/Runtime/Internal/UI/Modals/StartingInstructionModal.cs +1 -1
- package/Runtime/Public/Replay/ReplayPlaybackEngine.cs +71 -2
- package/Runtime/Resources/Fonts/Wonder Boys/Wonder Boys.asset +394 -379
- package/Runtime/Resources/HyperSDKSettings.asset +2 -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/UIPrefabs/ReplayController.prefab +295 -15
- package/Runtime/Resources/UIPrefabs/ReplayPausedModal.prefab +149 -120
- package/Runtime/Resources/UIPrefabs/ReplaySeekOverlay.prefab +291 -6
- package/Samples~/LaneRunner/Prefabs/DoubleScorePickup.prefab +1 -1
- package/Samples~/LaneRunner/Prefabs/Obstacle.prefab +1 -1
- package/Samples~/LaneRunner/Scripts/Gameplay/LaneRunnerSpawner.cs +1 -1
- package/Samples~/LaneRunner/Scripts/Gameplay/LaneRunnerTrackItem.cs +9 -2
- package/Samples~/LaneRunner/Scripts/Hyper/LaneRunnerTournamentAdapter.cs +1 -0
- package/package.json +1 -1
- /package/Runtime/{Public → Shared}/PlayerDeviceClassification.cs +0 -0
- /package/Runtime/{Public → Shared}/PlayerDeviceClassification.cs.meta +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,191 @@
|
|
|
1
|
+
# [1.11.0](https://github.com/mvmhyper/hyper-sdk/compare/v1.10.0...v1.11.0) (2026-09-23)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **sdk:** promote replay support and stability improvements to stable ([#159](https://github.com/mvmhyper/hyper-sdk/issues/159)) ([8172b37](https://github.com/mvmhyper/hyper-sdk/commit/8172b376cc587d139a43c4f4b4204f5c29af7aef))
|
|
7
|
+
|
|
8
|
+
# [1.11.0-beta.33](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.32...v1.11.0-beta.33) (2026-09-11)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **ui:** preserve mobile landscape canvas scaling ([c8a3f27](https://github.com/mvmhyper/hyper-sdk/commit/c8a3f2793bddaf89971a33d8752546a502de80e4))
|
|
14
|
+
|
|
15
|
+
# [1.11.0-beta.32](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.31...v1.11.0-beta.32) (2026-09-11)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* **ui:** set landscape canvas scaler match to 0.75 ([edc44eb](https://github.com/mvmhyper/hyper-sdk/commit/edc44ebcc229d68ed40eb60b05df3ed25c5053f8))
|
|
21
|
+
|
|
22
|
+
# [1.11.0-beta.31](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.30...v1.11.0-beta.31) (2026-09-09)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Bug Fixes
|
|
26
|
+
|
|
27
|
+
* prevent gameplay timers jumping after pause ([d9d9de4](https://github.com/mvmhyper/hyper-sdk/commit/d9d9de4b7c71a0493b379bfb3f8e7712785c1401))
|
|
28
|
+
|
|
29
|
+
# [1.11.0-beta.30](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.29...v1.11.0-beta.30) (2026-09-08)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
### Bug Fixes
|
|
33
|
+
|
|
34
|
+
* **replay:** improve seek slider handle usability ([10c4847](https://github.com/mvmhyper/hyper-sdk/commit/10c48474c6dff689903aae99bff40215152710f6))
|
|
35
|
+
|
|
36
|
+
# [1.11.0-beta.29](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.28...v1.11.0-beta.29) (2026-09-08)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
### Bug Fixes
|
|
40
|
+
|
|
41
|
+
* **replay:** simplify seek progress presentation ([16cf45a](https://github.com/mvmhyper/hyper-sdk/commit/16cf45afb3bf4fed8abc094ce2405237f0bf3b1d))
|
|
42
|
+
|
|
43
|
+
# [1.11.0-beta.28](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.27...v1.11.0-beta.28) (2026-09-08)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
### Features
|
|
47
|
+
|
|
48
|
+
* update replay playback speed options ([fc5f653](https://github.com/mvmhyper/hyper-sdk/commit/fc5f65350b31425c53a131b7c44e8780e1b0ce2d))
|
|
49
|
+
|
|
50
|
+
# [1.11.0-beta.27](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.26...v1.11.0-beta.27) (2026-09-08)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
### Features
|
|
54
|
+
|
|
55
|
+
* **replay:** increase seek reconstruction speed ([97ce729](https://github.com/mvmhyper/hyper-sdk/commit/97ce72978d64711e0463def42283704e5d880266))
|
|
56
|
+
|
|
57
|
+
# [1.11.0-beta.26](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.25...v1.11.0-beta.26) (2026-09-07)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
### Bug Fixes
|
|
61
|
+
|
|
62
|
+
* **sample:** refine replay integration template ([5a345df](https://github.com/mvmhyper/hyper-sdk/commit/5a345df87d19a6df11af4117fbeed1e21e8e9f9a))
|
|
63
|
+
|
|
64
|
+
# [1.11.0-beta.25](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.24...v1.11.0-beta.25) (2026-09-04)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
### Features
|
|
68
|
+
|
|
69
|
+
* **replay:** include final score metadata ([463dcad](https://github.com/mvmhyper/hyper-sdk/commit/463dcadd4df5e5684f3be328b0ec361f25f26f2a))
|
|
70
|
+
|
|
71
|
+
# [1.11.0-beta.24](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.23...v1.11.0-beta.24) (2026-09-04)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
### Bug Fixes
|
|
75
|
+
|
|
76
|
+
* **replay:** add 1.5x playback speed ([3f7875f](https://github.com/mvmhyper/hyper-sdk/commit/3f7875fcc4934ed01aaa521dce45327a177f67a6))
|
|
77
|
+
|
|
78
|
+
# [1.11.0-beta.23](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.22...v1.11.0-beta.23) (2026-09-03)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
### Bug Fixes
|
|
82
|
+
|
|
83
|
+
* **replay:** smooth read-only progress display ([ead4579](https://github.com/mvmhyper/hyper-sdk/commit/ead45798883b24e4b4354f3aab22400a1399e212))
|
|
84
|
+
|
|
85
|
+
# [1.11.0-beta.22](https://github.com/mvmhyper/hyper-sdk/compare/v1.11.0-beta.21...v1.11.0-beta.22) (2026-09-03)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
### Features
|
|
89
|
+
|
|
90
|
+
* **replay:** finalize playback controls and settings ([559a7e4](https://github.com/mvmhyper/hyper-sdk/commit/559a7e48d9998efa022fe87253645dc13f83e901))
|
|
91
|
+
|
|
92
|
+
# [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)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
### Bug Fixes
|
|
96
|
+
|
|
97
|
+
* **replay:** align gameplay activities to fixed ticks ([1e681b9](https://github.com/mvmhyper/hyper-sdk/commit/1e681b9c7f314a48c417f6e76cb2d4024c890ad3))
|
|
98
|
+
|
|
99
|
+
# [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)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
### Bug Fixes
|
|
103
|
+
|
|
104
|
+
* **replay:** separate replay restart configuration ([de01d37](https://github.com/mvmhyper/hyper-sdk/commit/de01d37027fdde5d4f8803fa10e060d48a080316))
|
|
105
|
+
|
|
106
|
+
# [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)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
### Bug Fixes
|
|
110
|
+
|
|
111
|
+
* **replay:** stop seeking at requested progress ([54bf74a](https://github.com/mvmhyper/hyper-sdk/commit/54bf74a4b66b7c19e1398acd611a7d9557ccbcf3))
|
|
112
|
+
|
|
113
|
+
# [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)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
### Features
|
|
117
|
+
|
|
118
|
+
* **replay:** support custom replay restarts ([bf722ab](https://github.com/mvmhyper/hyper-sdk/commit/bf722abe48add18c356922c60231cb2017e28443))
|
|
119
|
+
|
|
120
|
+
# [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)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
### Features
|
|
124
|
+
|
|
125
|
+
* **replay:** refine seek loading progress ([3d01f94](https://github.com/mvmhyper/hyper-sdk/commit/3d01f94d7e6ce360a61dd3d257149cf7f3237bcb))
|
|
126
|
+
|
|
127
|
+
# [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)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
### Bug Fixes
|
|
131
|
+
|
|
132
|
+
* **replay:** show seek preparation progress ([60213f7](https://github.com/mvmhyper/hyper-sdk/commit/60213f784c5bff39da4634590545fe4d0e4c0911))
|
|
133
|
+
|
|
134
|
+
# [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)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
### Features
|
|
138
|
+
|
|
139
|
+
* **replay:** show seek completion progress ([4e7c1b8](https://github.com/mvmhyper/hyper-sdk/commit/4e7c1b807bd9f34b97477ef39aa9ca3c06316ef3))
|
|
140
|
+
|
|
141
|
+
# [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)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
### Bug Fixes
|
|
145
|
+
|
|
146
|
+
* **replay:** keep seek loader animating ([7e13938](https://github.com/mvmhyper/hyper-sdk/commit/7e13938ce718a238506c08c30744ff24ed7fa710))
|
|
147
|
+
|
|
148
|
+
# [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)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
### Bug Fixes
|
|
152
|
+
|
|
153
|
+
* **replay:** reduce default seek speed to 10x ([ccaf5b9](https://github.com/mvmhyper/hyper-sdk/commit/ccaf5b9807fd9439627072518317ad7f079e544c))
|
|
154
|
+
|
|
155
|
+
# [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)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
### Bug Fixes
|
|
159
|
+
|
|
160
|
+
* **replay:** reduce default seek speed ([d757710](https://github.com/mvmhyper/hyper-sdk/commit/d757710d107a0a496c9d7daa1434004a682bd355))
|
|
161
|
+
|
|
162
|
+
# [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)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
### Bug Fixes
|
|
166
|
+
|
|
167
|
+
* **replay:** apply 30x seek speed on beta ([564769e](https://github.com/mvmhyper/hyper-sdk/commit/564769e4764f27fd301f0e1dc52a4434635f93b7))
|
|
168
|
+
* **replay:** reduce default seek speed ([2cd0a34](https://github.com/mvmhyper/hyper-sdk/commit/2cd0a34c6390725d1c57fc3fa5f691f618c45083))
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
### Features
|
|
172
|
+
|
|
173
|
+
* **replay:** increase default seek speed ([d1a5a46](https://github.com/mvmhyper/hyper-sdk/commit/d1a5a464c1e3e149255bf0d2d183439e9c29cfb3))
|
|
174
|
+
|
|
175
|
+
# [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)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
### Bug Fixes
|
|
179
|
+
|
|
180
|
+
* **replay:** reduce default seek speed ([f70551a](https://github.com/mvmhyper/hyper-sdk/commit/f70551aea942274ace1cb952ddae4e9edb0c1c12))
|
|
181
|
+
|
|
182
|
+
# [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)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
### Bug Fixes
|
|
186
|
+
|
|
187
|
+
* **replay:** show loader while exiting paused replay ([4a2e7a6](https://github.com/mvmhyper/hyper-sdk/commit/4a2e7a6045017ea8ed3ae3525271440dbf013e6c))
|
|
188
|
+
|
|
1
189
|
# [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)
|
|
2
190
|
|
|
3
191
|
|
|
@@ -170,6 +170,21 @@ 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
|
+
"Replay Custom Restart",
|
|
176
|
+
"Use game-owned restart logic for replay Watch Again and seeking. " +
|
|
177
|
+
"Disabled uses HyperLoader to rebuild deterministic game state."),
|
|
178
|
+
settings.useCustomReplayRestartFlow);
|
|
179
|
+
|
|
180
|
+
EditorGUILayout.Space(12);
|
|
181
|
+
EditorGUILayout.LabelField("Replay Settings", EditorStyles.boldLabel);
|
|
182
|
+
settings.allowReplaySeeking = EditorGUILayout.Toggle(
|
|
183
|
+
new GUIContent(
|
|
184
|
+
"Allow Replay Seeking",
|
|
185
|
+
"Allow viewers to seek using the replay progress bar. " +
|
|
186
|
+
"Leave disabled until accelerated replay reconstruction is validated for this game."),
|
|
187
|
+
settings.allowReplaySeeking);
|
|
173
188
|
|
|
174
189
|
EditorGUILayout.Space(12);
|
|
175
190
|
// 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
|
|
@@ -448,7 +448,11 @@ namespace Hyper.Internal
|
|
|
448
448
|
return false;
|
|
449
449
|
}
|
|
450
450
|
|
|
451
|
-
ReplaySessionState.SetMetadata(
|
|
451
|
+
ReplaySessionState.SetMetadata(
|
|
452
|
+
replay.PlayerName,
|
|
453
|
+
replay.AvatarUrl,
|
|
454
|
+
replay.Seed,
|
|
455
|
+
replay.FinalScore);
|
|
452
456
|
ReplaySessionState.SetReplayData(replay.ActivityNdjson);
|
|
453
457
|
HyperDebug.Log($"Replay loaded from {path}");
|
|
454
458
|
return true;
|
|
@@ -15,6 +15,8 @@ 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
|
|
|
@@ -22,6 +24,7 @@ namespace Hyper.Internal
|
|
|
22
24
|
private static bool _isSoftRestarting;
|
|
23
25
|
private static bool _replayRandomResetPending;
|
|
24
26
|
private static bool _replayCustomRestartPending;
|
|
27
|
+
private static int _replayCustomRestartVersion;
|
|
25
28
|
private static bool _customLoadingComplete;
|
|
26
29
|
private static bool _customLoadingActive;
|
|
27
30
|
private static float _customLoadingProgress;
|
|
@@ -123,7 +126,8 @@ namespace Hyper.Internal
|
|
|
123
126
|
}
|
|
124
127
|
|
|
125
128
|
/// <summary>
|
|
126
|
-
/// Restarts replay playback
|
|
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.
|
|
127
131
|
/// </summary>
|
|
128
132
|
internal static void RestartReplaySession()
|
|
129
133
|
{
|
|
@@ -147,8 +151,64 @@ namespace Hyper.Internal
|
|
|
147
151
|
|
|
148
152
|
_replayCustomRestartPending = false;
|
|
149
153
|
_replayRandomResetPending = false;
|
|
154
|
+
int restartVersion = ++_replayCustomRestartVersion;
|
|
150
155
|
_replayManager?.PrepareForRestart();
|
|
151
156
|
|
|
157
|
+
if (_settings != null && _settings.useCustomReplayRestartFlow &&
|
|
158
|
+
_host != null && _gameManager != null && _eventManager != null)
|
|
159
|
+
{
|
|
160
|
+
_replayCustomRestartPending = true;
|
|
161
|
+
_replayRandomResetPending = true;
|
|
162
|
+
_gameManager.ResetUIStateForCustomRestart();
|
|
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
|
+
}
|
|
184
|
+
}
|
|
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;
|
|
152
212
|
if (_host != null)
|
|
153
213
|
{
|
|
154
214
|
_host.StartCoroutine(RestartSessionCoroutine());
|
|
@@ -443,6 +503,7 @@ namespace Hyper.Internal
|
|
|
443
503
|
_customLoadingProgress = 0f;
|
|
444
504
|
_replayRandomResetPending = false;
|
|
445
505
|
_replayCustomRestartPending = false;
|
|
506
|
+
_replayCustomRestartVersion++;
|
|
446
507
|
_fixedSimulationTimeSeconds = 0d;
|
|
447
508
|
|
|
448
509
|
if (_singletonObject != null)
|
|
@@ -504,6 +565,7 @@ namespace Hyper.Internal
|
|
|
504
565
|
_customLoadingProgress = 0f;
|
|
505
566
|
_replayRandomResetPending = false;
|
|
506
567
|
_replayCustomRestartPending = false;
|
|
568
|
+
_replayCustomRestartVersion++;
|
|
507
569
|
_fixedSimulationTimeSeconds = 0d;
|
|
508
570
|
}
|
|
509
571
|
}
|
|
@@ -179,7 +179,8 @@ namespace Hyper.Internal.Managers
|
|
|
179
179
|
ReplaySessionState.SetMetadata(
|
|
180
180
|
replay.PlayerName,
|
|
181
181
|
replay.AvatarUrl,
|
|
182
|
-
replay.Seed
|
|
182
|
+
replay.Seed,
|
|
183
|
+
replay.FinalScore);
|
|
183
184
|
ReplaySessionState.SetReplayData(replay.ActivityNdjson);
|
|
184
185
|
HyperDebug.Log($"Replay downloaded for entry {entryId}.");
|
|
185
186
|
onSuccess?.Invoke();
|
|
@@ -289,9 +290,10 @@ namespace Hyper.Internal.Managers
|
|
|
289
290
|
string seedLine = reader.ReadLine();
|
|
290
291
|
string nameLine = reader.ReadLine();
|
|
291
292
|
string avatarLine = reader.ReadLine();
|
|
293
|
+
string scoreLine = reader.ReadLine();
|
|
292
294
|
string activities = reader.ReadToEnd();
|
|
293
295
|
|
|
294
|
-
if (seedLine == null || nameLine == null || avatarLine == null)
|
|
296
|
+
if (seedLine == null || nameLine == null || avatarLine == null || scoreLine == null)
|
|
295
297
|
{
|
|
296
298
|
error = "The replay response is missing required metadata.";
|
|
297
299
|
return false;
|
|
@@ -302,6 +304,7 @@ namespace Hyper.Internal.Managers
|
|
|
302
304
|
JArray seedData = JArray.Parse(seedLine);
|
|
303
305
|
JArray nameData = JArray.Parse(nameLine);
|
|
304
306
|
JArray avatarData = JArray.Parse(avatarLine);
|
|
307
|
+
JArray scoreData = JArray.Parse(scoreLine);
|
|
305
308
|
|
|
306
309
|
if (seedData.Count != 1 ||
|
|
307
310
|
seedData[0].Type != JTokenType.Integer ||
|
|
@@ -327,6 +330,18 @@ namespace Hyper.Internal.Managers
|
|
|
327
330
|
return false;
|
|
328
331
|
}
|
|
329
332
|
|
|
333
|
+
if (scoreData.Count != 1 ||
|
|
334
|
+
scoreData[0].Type != JTokenType.Integer ||
|
|
335
|
+
!int.TryParse(
|
|
336
|
+
scoreData[0].ToString(),
|
|
337
|
+
NumberStyles.Integer,
|
|
338
|
+
CultureInfo.InvariantCulture,
|
|
339
|
+
out int finalScore))
|
|
340
|
+
{
|
|
341
|
+
error = "Replay metadata contains an invalid final score.";
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
344
|
+
|
|
330
345
|
if (string.IsNullOrWhiteSpace(activities))
|
|
331
346
|
{
|
|
332
347
|
error = "The replay response contains no gameplay activities.";
|
|
@@ -337,6 +352,7 @@ namespace Hyper.Internal.Managers
|
|
|
337
352
|
seed,
|
|
338
353
|
nameData[0].Value<string>() ?? string.Empty,
|
|
339
354
|
avatarData[0].Value<string>() ?? string.Empty,
|
|
355
|
+
finalScore,
|
|
340
356
|
activities);
|
|
341
357
|
|
|
342
358
|
return true;
|
|
@@ -354,13 +370,20 @@ namespace Hyper.Internal.Managers
|
|
|
354
370
|
internal long Seed { get; }
|
|
355
371
|
internal string PlayerName { get; }
|
|
356
372
|
internal string AvatarUrl { get; }
|
|
373
|
+
internal int FinalScore { get; }
|
|
357
374
|
internal string ActivityNdjson { get; }
|
|
358
375
|
|
|
359
|
-
internal ReplayResponse(
|
|
376
|
+
internal ReplayResponse(
|
|
377
|
+
long seed,
|
|
378
|
+
string playerName,
|
|
379
|
+
string avatarUrl,
|
|
380
|
+
int finalScore,
|
|
381
|
+
string activityNdjson)
|
|
360
382
|
{
|
|
361
383
|
Seed = seed;
|
|
362
384
|
PlayerName = playerName;
|
|
363
385
|
AvatarUrl = avatarUrl;
|
|
386
|
+
FinalScore = finalScore;
|
|
364
387
|
ActivityNdjson = activityNdjson;
|
|
365
388
|
}
|
|
366
389
|
}
|
|
@@ -375,6 +375,7 @@ namespace Hyper.Internal.Managers
|
|
|
375
375
|
new object[] { HyperRandom.CurrentSeed }));
|
|
376
376
|
_editorReplay.AppendLine(JsonConvert.SerializeObject(new object[] { "hypergamer" }));
|
|
377
377
|
_editorReplay.AppendLine(JsonConvert.SerializeObject(new object[] { string.Empty }));
|
|
378
|
+
_editorReplayMetadataLength = _editorReplay.Length;
|
|
378
379
|
#endif
|
|
379
380
|
_replayRecorder?.StartSession();
|
|
380
381
|
}
|
|
@@ -426,6 +427,7 @@ namespace Hyper.Internal.Managers
|
|
|
426
427
|
|
|
427
428
|
#if UNITY_EDITOR
|
|
428
429
|
private readonly StringBuilder _editorReplay = new StringBuilder(4096);
|
|
430
|
+
private int _editorReplayMetadataLength;
|
|
429
431
|
|
|
430
432
|
private void CaptureEditorReplayActivity(object[] activity)
|
|
431
433
|
{
|
|
@@ -434,6 +436,8 @@ namespace Hyper.Internal.Managers
|
|
|
434
436
|
|
|
435
437
|
private void SaveEditorReplay()
|
|
436
438
|
{
|
|
439
|
+
string finalScoreLine = JsonConvert.SerializeObject(new object[] { CurrentScore }) + Environment.NewLine;
|
|
440
|
+
_editorReplay.Insert(_editorReplayMetadataLength, finalScoreLine);
|
|
437
441
|
try
|
|
438
442
|
{
|
|
439
443
|
File.WriteAllText(ReplaySessionState.EditorReplayFilePath, _editorReplay.ToString());
|
|
@@ -443,6 +447,10 @@ namespace Hyper.Internal.Managers
|
|
|
443
447
|
{
|
|
444
448
|
HyperDebug.LogWarning($"Unable to save Editor replay: {exception.Message}");
|
|
445
449
|
}
|
|
450
|
+
finally
|
|
451
|
+
{
|
|
452
|
+
_editorReplay.Remove(_editorReplayMetadataLength, finalScoreLine.Length);
|
|
453
|
+
}
|
|
446
454
|
}
|
|
447
455
|
#endif
|
|
448
456
|
|
|
@@ -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();
|
|
@@ -1334,7 +1334,7 @@ namespace Hyper.Internal.Managers
|
|
|
1334
1334
|
_canvasScaler = _canvas.GetComponent<CanvasScaler>();
|
|
1335
1335
|
_canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
|
1336
1336
|
_canvasScaler.referenceResolution = new Vector2(1080, 2160);
|
|
1337
|
-
_canvasScaler.matchWidthOrHeight = IsPortrait() ? 1f : 0.593f;
|
|
1337
|
+
_canvasScaler.matchWidthOrHeight = IsPortrait() ? 1f : (PlayerDeviceClassification.PlayerDeviceIsPC ? 0.75f : 0.593f);
|
|
1338
1338
|
|
|
1339
1339
|
CreateHyperCanvasSafeArea();
|
|
1340
1340
|
CreateHyperCanvasBlockerUI();
|
|
@@ -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()
|
|
@@ -103,14 +103,28 @@ namespace Hyper.Internal.Managers
|
|
|
103
103
|
if (Mathf.Approximately(Time.timeScale, 0f))
|
|
104
104
|
return;
|
|
105
105
|
|
|
106
|
-
float gameTimerDelta =
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
float gameTimerDelta = GetGameTimerDelta(
|
|
107
|
+
_gameManager != null && _gameManager.IsReplayMode,
|
|
108
|
+
Time.fixedDeltaTime,
|
|
109
|
+
Time.timeScale);
|
|
109
110
|
|
|
110
111
|
UpdatePracticeTimer(gameTimerDelta);
|
|
111
112
|
UpdateBattleTimer(gameTimerDelta);
|
|
112
113
|
}
|
|
113
114
|
|
|
115
|
+
internal static float GetGameTimerDelta(
|
|
116
|
+
bool isReplayMode,
|
|
117
|
+
float fixedDeltaTime,
|
|
118
|
+
float timeScale)
|
|
119
|
+
{
|
|
120
|
+
if (timeScale <= 0f) return 0f;
|
|
121
|
+
|
|
122
|
+
// The first FixedUpdate after a pause can report the whole paused
|
|
123
|
+
// interval in fixedUnscaledDeltaTime. Derive one live simulation
|
|
124
|
+
// step instead, keeping real-time duration at custom time scales.
|
|
125
|
+
return isReplayMode ? fixedDeltaTime : fixedDeltaTime / timeScale;
|
|
126
|
+
}
|
|
127
|
+
|
|
114
128
|
public void Reset()
|
|
115
129
|
{
|
|
116
130
|
_practiceTimer = 0;
|
|
@@ -299,9 +313,9 @@ namespace Hyper.Internal.Managers
|
|
|
299
313
|
}
|
|
300
314
|
|
|
301
315
|
_battleTimer -= delta;
|
|
302
|
-
if (_battleTimer <=
|
|
316
|
+
if (_battleTimer <= 0f || Mathf.Approximately(_battleTimer, 0f))
|
|
303
317
|
{
|
|
304
|
-
_battleTimer =
|
|
318
|
+
_battleTimer = 0f;
|
|
305
319
|
if (!_timeUpTriggered)
|
|
306
320
|
{
|
|
307
321
|
QueueTimeUp();
|
|
@@ -314,7 +328,8 @@ namespace Hyper.Internal.Managers
|
|
|
314
328
|
{
|
|
315
329
|
_battleTimer = _sessionTimer;
|
|
316
330
|
|
|
317
|
-
if (_battleTimer <=
|
|
331
|
+
if ((_battleTimer <= 0f || Mathf.Approximately(_battleTimer, 0f)) &&
|
|
332
|
+
!_timeUpTriggered)
|
|
318
333
|
{
|
|
319
334
|
QueueTimeUp();
|
|
320
335
|
}
|
|
@@ -14,6 +14,7 @@ namespace Hyper.Internal
|
|
|
14
14
|
public static string AvatarUrl { get; private set; }
|
|
15
15
|
public static string EntryId { get; private set; }
|
|
16
16
|
public static string ReplayNdjson { get; private set; }
|
|
17
|
+
public static int? FinalScore { get; private set; }
|
|
17
18
|
public static Texture2D AvatarTexture { get; private set; }
|
|
18
19
|
public static bool HasReplayData => !string.IsNullOrWhiteSpace(ReplayNdjson);
|
|
19
20
|
public static long OriginalRandomSeed { get; private set; }
|
|
@@ -48,6 +49,7 @@ namespace Hyper.Internal
|
|
|
48
49
|
AvatarUrl = avatarUrl ?? string.Empty;
|
|
49
50
|
EntryId = entryId ?? string.Empty;
|
|
50
51
|
ReplayNdjson = string.Empty;
|
|
52
|
+
FinalScore = null;
|
|
51
53
|
ReleaseAvatarTexture();
|
|
52
54
|
OriginalRandomSeed = originalRandomSeed;
|
|
53
55
|
Progress01 = 0f;
|
|
@@ -61,13 +63,18 @@ namespace Hyper.Internal
|
|
|
61
63
|
GameplayStartProgress01 = 0f;
|
|
62
64
|
}
|
|
63
65
|
|
|
64
|
-
public static void SetMetadata(
|
|
66
|
+
public static void SetMetadata(
|
|
67
|
+
string playerName,
|
|
68
|
+
string avatarUrl,
|
|
69
|
+
long originalRandomSeed,
|
|
70
|
+
int finalScore)
|
|
65
71
|
{
|
|
66
72
|
if (!IsActive) return;
|
|
67
73
|
|
|
68
74
|
PlayerName = playerName ?? string.Empty;
|
|
69
75
|
AvatarUrl = avatarUrl ?? string.Empty;
|
|
70
76
|
OriginalRandomSeed = originalRandomSeed;
|
|
77
|
+
FinalScore = finalScore;
|
|
71
78
|
}
|
|
72
79
|
|
|
73
80
|
public static void SetReplayData(string ndjson)
|
|
@@ -83,10 +90,10 @@ namespace Hyper.Internal
|
|
|
83
90
|
AvatarTexture = texture;
|
|
84
91
|
}
|
|
85
92
|
|
|
86
|
-
public static
|
|
93
|
+
public static bool SetProgress(float progress)
|
|
87
94
|
{
|
|
88
|
-
if (!IsActive) return;
|
|
89
|
-
if (IsSeeking && !_seekPlaybackReady) return;
|
|
95
|
+
if (!IsActive) return false;
|
|
96
|
+
if (IsSeeking && !_seekPlaybackReady) return false;
|
|
90
97
|
float rawProgress = Math.Max(0f, Math.Min(1f, progress));
|
|
91
98
|
Progress01 = GameplayStartProgress01 >= 1f
|
|
92
99
|
? 0f
|
|
@@ -101,7 +108,10 @@ namespace Hyper.Internal
|
|
|
101
108
|
PlaybackSpeed = UserPlaybackSpeed;
|
|
102
109
|
RestoreAudioAfterSeek();
|
|
103
110
|
SeekCompleted?.Invoke(PlaybackSpeed);
|
|
111
|
+
return true;
|
|
104
112
|
}
|
|
113
|
+
|
|
114
|
+
return false;
|
|
105
115
|
}
|
|
106
116
|
|
|
107
117
|
public static void SetPlaybackSpeed(float speed)
|
|
@@ -190,6 +200,7 @@ namespace Hyper.Internal
|
|
|
190
200
|
AvatarUrl = string.Empty;
|
|
191
201
|
EntryId = string.Empty;
|
|
192
202
|
ReplayNdjson = string.Empty;
|
|
203
|
+
FinalScore = null;
|
|
193
204
|
ReleaseAvatarTexture();
|
|
194
205
|
OriginalRandomSeed = 0;
|
|
195
206
|
Progress01 = 0f;
|
|
@@ -76,6 +76,16 @@ namespace Hyper.Internal
|
|
|
76
76
|
"instead of using default restart. Listen to HyperSDK.Event.OnCustomRestart in your game manager.")]
|
|
77
77
|
public bool useCustomRestartFlow = false;
|
|
78
78
|
|
|
79
|
+
[Tooltip("Use the game-owned custom restart flow for replay Watch Again and seeking. " +
|
|
80
|
+
"Leave disabled to rebuild the game through HyperLoader for deterministic replay state.")]
|
|
81
|
+
public bool useCustomReplayRestartFlow = false;
|
|
82
|
+
|
|
83
|
+
[Space(20)]
|
|
84
|
+
[Header("Replay Settings")]
|
|
85
|
+
[Tooltip("Allow replay viewers to seek from the replay progress bar. " +
|
|
86
|
+
"Leave disabled until the game has been validated for accelerated replay reconstruction.")]
|
|
87
|
+
public bool allowReplaySeeking = false;
|
|
88
|
+
|
|
79
89
|
#endregion
|
|
80
90
|
|
|
81
91
|
#region Editor Testing
|