app.hypergames.hypersdk 1.10.0 → 1.11.0-beta.2
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 +34 -0
- package/Editor/Scripts/Setup/HyperSDKInstaller.cs +42 -0
- package/Editor/Scripts/Tools/HyperGameModeMenu.cs +27 -7
- package/Runtime/Internal/AssemblyInfo.cs +1 -0
- package/Runtime/Internal/Bootstrap/HyperLoader.cs +186 -8
- package/Runtime/Internal/Core/HyperRuntime.cs +82 -0
- package/Runtime/Internal/Core/HyperRuntimeHost.cs +6 -0
- package/Runtime/Internal/Data/URLData.cs +18 -1
- package/Runtime/Internal/Managers/BackendManager.cs +281 -24
- package/Runtime/Internal/Managers/DataManager.cs +207 -21
- package/Runtime/Internal/Managers/GameManager.cs +365 -17
- package/Runtime/Internal/Managers/ReplayManager.cs +117 -0
- package/Runtime/Internal/Managers/ReplayManager.cs.meta +11 -0
- package/Runtime/Internal/Managers/TimeManager.cs +54 -12
- package/Runtime/Internal/Replay/ReplayActivityRecorder.cs +182 -0
- package/Runtime/Internal/Replay/ReplayActivityRecorder.cs.meta +2 -0
- package/Runtime/Internal/Replay/ReplaySessionState.cs +181 -0
- package/Runtime/Internal/Replay/ReplaySessionState.cs.meta +2 -0
- package/Runtime/Internal/Replay.meta +8 -0
- package/Runtime/Internal/ScriptableObjects/HyperSDKSettings.cs +5 -0
- package/Runtime/Internal/UI/Animation/LoadingTextAnimation.cs +15 -1
- package/Runtime/Internal/UI/Components/ControlBar.cs +25 -2
- package/Runtime/Internal/UI/Components/PauseButton.cs +4 -1
- package/Runtime/Internal/UI/Components/ReplayController.cs +527 -0
- package/Runtime/Internal/UI/Components/ReplayController.cs.meta +2 -0
- package/Runtime/Internal/UI/Components/ReplayMarkerPulse.cs +89 -0
- package/Runtime/Internal/UI/Components/ReplayMarkerPulse.cs.meta +2 -0
- package/Runtime/Internal/UI/Components/ReplayPresentationCanvas.cs +183 -0
- package/Runtime/Internal/UI/Components/ReplayPresentationCanvas.cs.meta +2 -0
- package/Runtime/Internal/UI/Modals/LoadingFailedModal.cs +12 -0
- package/Runtime/Internal/UI/Modals/ReplayOverModal.cs +61 -0
- package/Runtime/Internal/UI/Modals/ReplayOverModal.cs.meta +2 -0
- package/Runtime/Internal/UI/Modals/StartingInstructionModal.cs +38 -29
- package/Runtime/Public/AssemblyInfo.cs +3 -0
- package/Runtime/Public/AssemblyInfo.cs.meta +2 -0
- package/Runtime/Public/Core/HyperSDK.cs +305 -109
- package/Runtime/Public/Hyper.asmdef +2 -1
- package/Runtime/Public/Replay/ReplayPlaybackEngine.cs +555 -0
- package/Runtime/Public/Replay/ReplayPlaybackEngine.cs.meta +2 -0
- package/Runtime/Public/Replay.meta +8 -0
- package/Runtime/Resources/Fonts/Nunito/Nunito-Light SDF.asset +528 -521
- package/Runtime/Resources/Materials/HyperReplayScanlines.preset +340 -0
- package/Runtime/Resources/Materials/HyperReplayScanlines.preset.meta +8 -0
- package/Runtime/Resources/Materials/ReplayScanlineOverlay.mat +55 -0
- package/Runtime/Resources/Materials/ReplayScanlineOverlay.mat.meta +8 -0
- package/Runtime/Resources/Shaders/ReplayScanlineOverlay.shader +150 -0
- package/Runtime/Resources/Shaders/ReplayScanlineOverlay.shader.meta +10 -0
- package/Runtime/Resources/Sprites/Replays/Fallback avatar.png +0 -0
- package/Runtime/Resources/Sprites/Replays/Fallback avatar.png.meta +156 -0
- package/Runtime/Resources/Sprites/Replays/Recording.png +0 -0
- package/Runtime/Resources/Sprites/Replays/Recording.png.meta +156 -0
- package/Runtime/Resources/Sprites/Replays/Replay frame.png +0 -0
- package/Runtime/Resources/Sprites/Replays/Replay frame.png.meta +156 -0
- package/Runtime/Resources/Sprites/Replays/Replay modal icon.png +0 -0
- package/Runtime/Resources/Sprites/Replays/Replay modal icon.png.meta +156 -0
- package/Runtime/Resources/Sprites/Replays.meta +8 -0
- package/Runtime/Resources/UIPrefabs/ControlBar.prefab +169 -2
- package/Runtime/Resources/UIPrefabs/GamePausedModal_Battle.prefab +1 -1
- package/Runtime/Resources/UIPrefabs/ReplayController.prefab +1269 -0
- package/Runtime/Resources/UIPrefabs/ReplayController.prefab.meta +7 -0
- package/Runtime/Resources/UIPrefabs/ReplayInputBlocker.prefab +90 -0
- package/Runtime/Resources/UIPrefabs/ReplayInputBlocker.prefab.meta +7 -0
- package/Runtime/Resources/UIPrefabs/ReplayOverModal.prefab +958 -0
- package/Runtime/Resources/UIPrefabs/ReplayOverModal.prefab.meta +7 -0
- package/Runtime/Resources/UIPrefabs/ReplaySeekOverlay.prefab +189 -0
- package/Runtime/Resources/UIPrefabs/ReplaySeekOverlay.prefab.meta +7 -0
- package/Runtime/Resources/UIPrefabs/SnackBar.prefab +2 -2
- package/Runtime/Shared/AssemblyInfo.cs +5 -0
- package/Runtime/Shared/AssemblyInfo.cs.meta +11 -0
- package/Runtime/Shared/DTOs/Enums.cs +8 -3
- package/Runtime/Shared/DTOs/Score/ScoreSnapshot.cs +13 -1
- package/Runtime/Shared/Replay/IReplayPlaybackEngine.cs +37 -0
- package/Runtime/Shared/Replay/IReplayPlaybackEngine.cs.meta +11 -0
- package/Runtime/Shared/Replay.meta +8 -0
- package/Samples~/LaneRunner/LaneRunnerSample.unity +1603 -0
- package/Samples~/LaneRunner/LaneRunnerSample.unity.meta +7 -0
- package/Samples~/LaneRunner/Materials/DoubleScore.mat +86 -0
- package/Samples~/LaneRunner/Materials/DoubleScore.mat.meta +8 -0
- package/Samples~/LaneRunner/Materials/Ground.mat +84 -0
- package/Samples~/LaneRunner/Materials/Ground.mat.meta +8 -0
- package/Samples~/LaneRunner/Materials/Lane.mat +84 -0
- package/Samples~/LaneRunner/Materials/Lane.mat.meta +8 -0
- package/Samples~/LaneRunner/Materials/LaneMarker.mat +84 -0
- package/Samples~/LaneRunner/Materials/LaneMarker.mat.meta +8 -0
- package/Samples~/LaneRunner/Materials/Obstacle.mat +84 -0
- package/Samples~/LaneRunner/Materials/Obstacle.mat.meta +8 -0
- package/Samples~/LaneRunner/Materials/Player.mat +84 -0
- package/Samples~/LaneRunner/Materials/Player.mat.meta +8 -0
- package/Samples~/LaneRunner/Materials.meta +8 -0
- package/Samples~/LaneRunner/Prefabs/DoubleScorePickup.prefab +152 -0
- package/Samples~/LaneRunner/Prefabs/DoubleScorePickup.prefab.meta +7 -0
- package/Samples~/LaneRunner/Prefabs/Obstacle.prefab +152 -0
- package/Samples~/LaneRunner/Prefabs/Obstacle.prefab.meta +7 -0
- package/Samples~/LaneRunner/Prefabs.meta +8 -0
- package/Samples~/LaneRunner/README.md +35 -0
- package/Samples~/LaneRunner/README.md.meta +7 -0
- package/Samples~/LaneRunner/Scripts/Gameplay/LaneRunnerCommand.cs +9 -0
- package/Samples~/LaneRunner/Scripts/Gameplay/LaneRunnerCommand.cs.meta +2 -0
- package/Samples~/LaneRunner/Scripts/Gameplay/LaneRunnerGame.cs +93 -0
- package/Samples~/LaneRunner/Scripts/Gameplay/LaneRunnerGame.cs.meta +2 -0
- package/Samples~/LaneRunner/Scripts/Gameplay/LaneRunnerPlayer.cs +155 -0
- package/Samples~/LaneRunner/Scripts/Gameplay/LaneRunnerPlayer.cs.meta +2 -0
- package/Samples~/LaneRunner/Scripts/Gameplay/LaneRunnerSpawner.cs +110 -0
- package/Samples~/LaneRunner/Scripts/Gameplay/LaneRunnerSpawner.cs.meta +2 -0
- package/Samples~/LaneRunner/Scripts/Gameplay/LaneRunnerTrackItem.cs +41 -0
- package/Samples~/LaneRunner/Scripts/Gameplay/LaneRunnerTrackItem.cs.meta +2 -0
- package/Samples~/LaneRunner/Scripts/Gameplay.meta +8 -0
- package/Samples~/LaneRunner/Scripts/Hyper/LaneRunnerReplayAdapter.cs +62 -0
- package/Samples~/LaneRunner/Scripts/Hyper/LaneRunnerReplayAdapter.cs.meta +2 -0
- package/Samples~/LaneRunner/Scripts/Hyper/LaneRunnerTournamentAdapter.cs +64 -0
- package/Samples~/LaneRunner/Scripts/Hyper/LaneRunnerTournamentAdapter.cs.meta +2 -0
- package/Samples~/LaneRunner/Scripts/Hyper.meta +8 -0
- package/Samples~/LaneRunner/Scripts.meta +8 -0
- package/Tests.meta +8 -0
- package/package.json +8 -1
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
using System.Collections;
|
|
2
|
+
using UnityEngine;
|
|
3
|
+
using UnityEngine.UI;
|
|
4
|
+
|
|
5
|
+
namespace Hyper.Internal
|
|
6
|
+
{
|
|
7
|
+
[RequireComponent(typeof(Graphic))]
|
|
8
|
+
internal sealed class ReplayMarkerPulse : MonoBehaviour
|
|
9
|
+
{
|
|
10
|
+
[SerializeField, Range(0f, 1f)] private float minimumAlpha = 0.3f;
|
|
11
|
+
[SerializeField] private float fadeDuration = 0.8f;
|
|
12
|
+
|
|
13
|
+
private Graphic _graphic;
|
|
14
|
+
private Coroutine _pulseCoroutine;
|
|
15
|
+
|
|
16
|
+
private void Awake()
|
|
17
|
+
{
|
|
18
|
+
_graphic = GetComponent<Graphic>();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
private void OnEnable()
|
|
22
|
+
{
|
|
23
|
+
HyperRuntime.EventManager.OnGameStart += StartPulsing;
|
|
24
|
+
HyperRuntime.EventManager.OnGameEnded += StopPulsing;
|
|
25
|
+
SetAlpha(minimumAlpha);
|
|
26
|
+
|
|
27
|
+
if (HyperRuntime.GameManager != null && HyperRuntime.GameManager.HasGameStarted)
|
|
28
|
+
{
|
|
29
|
+
StartPulsing();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private void OnDisable()
|
|
34
|
+
{
|
|
35
|
+
if (HyperRuntime.EventManager != null)
|
|
36
|
+
{
|
|
37
|
+
HyperRuntime.EventManager.OnGameStart -= StartPulsing;
|
|
38
|
+
HyperRuntime.EventManager.OnGameEnded -= StopPulsing;
|
|
39
|
+
}
|
|
40
|
+
StopPulsing();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private void StartPulsing()
|
|
44
|
+
{
|
|
45
|
+
if (_pulseCoroutine != null) StopCoroutine(_pulseCoroutine);
|
|
46
|
+
_pulseCoroutine = StartCoroutine(Pulse());
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private void StopPulsing()
|
|
50
|
+
{
|
|
51
|
+
if (_pulseCoroutine != null)
|
|
52
|
+
{
|
|
53
|
+
StopCoroutine(_pulseCoroutine);
|
|
54
|
+
_pulseCoroutine = null;
|
|
55
|
+
}
|
|
56
|
+
SetAlpha(1f);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private IEnumerator Pulse()
|
|
60
|
+
{
|
|
61
|
+
float duration = Mathf.Max(0.05f, fadeDuration);
|
|
62
|
+
while (true)
|
|
63
|
+
{
|
|
64
|
+
yield return Fade(minimumAlpha, 1f, duration);
|
|
65
|
+
yield return Fade(1f, minimumAlpha, duration);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private IEnumerator Fade(float from, float to, float duration)
|
|
70
|
+
{
|
|
71
|
+
float elapsed = 0f;
|
|
72
|
+
while (elapsed < duration)
|
|
73
|
+
{
|
|
74
|
+
elapsed += Time.unscaledDeltaTime;
|
|
75
|
+
SetAlpha(Mathf.Lerp(from, to, elapsed / duration));
|
|
76
|
+
yield return null;
|
|
77
|
+
}
|
|
78
|
+
SetAlpha(to);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private void SetAlpha(float alpha)
|
|
82
|
+
{
|
|
83
|
+
if (_graphic == null) return;
|
|
84
|
+
Color color = _graphic.color;
|
|
85
|
+
color.a = alpha;
|
|
86
|
+
_graphic.color = color;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
using Hyper.Shared;
|
|
2
|
+
using UnityEngine;
|
|
3
|
+
using UnityEngine.UI;
|
|
4
|
+
|
|
5
|
+
namespace Hyper.Internal
|
|
6
|
+
{
|
|
7
|
+
/// <summary>
|
|
8
|
+
/// Owns replay-only UI independently from the session-scoped HyperCanvas.
|
|
9
|
+
/// The root survives only while a seek restart is in progress.
|
|
10
|
+
/// </summary>
|
|
11
|
+
internal sealed class ReplayPresentationCanvas : MonoBehaviour
|
|
12
|
+
{
|
|
13
|
+
private const int NormalSortingOrder = 9999;
|
|
14
|
+
private const int SeekingSortingOrder = 10001;
|
|
15
|
+
|
|
16
|
+
private static ReplayPresentationCanvas instance;
|
|
17
|
+
|
|
18
|
+
internal GameObject InputBlocker { get; private set; }
|
|
19
|
+
internal GameObject ControllerObject { get; private set; }
|
|
20
|
+
internal ReplayController Controller { get; private set; }
|
|
21
|
+
|
|
22
|
+
internal static ReplayPresentationCanvas GetOrCreate(bool isPortrait)
|
|
23
|
+
{
|
|
24
|
+
if (instance == null)
|
|
25
|
+
{
|
|
26
|
+
instance = FindFirstObjectByType<ReplayPresentationCanvas>();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (instance == null)
|
|
30
|
+
{
|
|
31
|
+
var root = new GameObject(
|
|
32
|
+
"ReplayPresentationCanvas",
|
|
33
|
+
typeof(RectTransform),
|
|
34
|
+
typeof(Canvas),
|
|
35
|
+
typeof(CanvasScaler),
|
|
36
|
+
typeof(GraphicRaycaster));
|
|
37
|
+
instance = root.AddComponent<ReplayPresentationCanvas>();
|
|
38
|
+
DontDestroyOnLoad(root);
|
|
39
|
+
instance.Build(isPortrait);
|
|
40
|
+
}
|
|
41
|
+
else
|
|
42
|
+
{
|
|
43
|
+
instance.ConfigureCanvas(isPortrait);
|
|
44
|
+
instance.EnsurePresentationObjects();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
instance.gameObject.SetActive(true);
|
|
48
|
+
instance.ControllerObject?.transform.SetAsLastSibling();
|
|
49
|
+
return instance;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
internal static bool IsPresentationRoot(GameObject root)
|
|
53
|
+
{
|
|
54
|
+
return instance != null && root == instance.gameObject;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
internal static void SetSeekingLayer(bool isSeeking)
|
|
58
|
+
{
|
|
59
|
+
if (instance == null) return;
|
|
60
|
+
Canvas canvas = instance.GetComponent<Canvas>();
|
|
61
|
+
if (canvas != null) canvas.sortingOrder = isSeeking ? SeekingSortingOrder : NormalSortingOrder;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
internal static void DestroyCurrent()
|
|
65
|
+
{
|
|
66
|
+
if (instance == null) return;
|
|
67
|
+
Destroy(instance.gameObject);
|
|
68
|
+
instance = null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private void Awake()
|
|
72
|
+
{
|
|
73
|
+
if (instance != null && instance != this)
|
|
74
|
+
{
|
|
75
|
+
Destroy(gameObject);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
instance = this;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private void OnDestroy()
|
|
83
|
+
{
|
|
84
|
+
if (instance == this) instance = null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private void Build(bool isPortrait)
|
|
88
|
+
{
|
|
89
|
+
ConfigureCanvas(isPortrait);
|
|
90
|
+
|
|
91
|
+
var safeArea = new GameObject("SafeArea", typeof(RectTransform));
|
|
92
|
+
RectTransform safeAreaRect = safeArea.GetComponent<RectTransform>();
|
|
93
|
+
safeAreaRect.SetParent(transform, false);
|
|
94
|
+
StretchToParent(safeAreaRect);
|
|
95
|
+
if (isPortrait) safeArea.AddComponent<SafeArea>();
|
|
96
|
+
|
|
97
|
+
CreateInputBlocker(safeAreaRect);
|
|
98
|
+
CreateController(safeAreaRect);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private void ConfigureCanvas(bool isPortrait)
|
|
102
|
+
{
|
|
103
|
+
Canvas canvas = GetComponent<Canvas>();
|
|
104
|
+
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
|
105
|
+
canvas.overrideSorting = true;
|
|
106
|
+
canvas.sortingOrder = ReplaySessionState.IsSeeking
|
|
107
|
+
? SeekingSortingOrder
|
|
108
|
+
: NormalSortingOrder;
|
|
109
|
+
|
|
110
|
+
CanvasScaler scaler = GetComponent<CanvasScaler>();
|
|
111
|
+
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
|
112
|
+
scaler.referenceResolution = new Vector2(1080f, 2160f);
|
|
113
|
+
scaler.matchWidthOrHeight = isPortrait ? 1f : 0.593f;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private void EnsurePresentationObjects()
|
|
117
|
+
{
|
|
118
|
+
Transform safeArea = transform.Find("SafeArea");
|
|
119
|
+
if (safeArea == null)
|
|
120
|
+
{
|
|
121
|
+
Build(Screen.height > Screen.width);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (InputBlocker == null)
|
|
126
|
+
{
|
|
127
|
+
Transform blocker = safeArea.Find("ReplayInputBlocker");
|
|
128
|
+
InputBlocker = blocker != null ? blocker.gameObject : null;
|
|
129
|
+
if (InputBlocker == null) CreateInputBlocker((RectTransform)safeArea);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (ControllerObject == null)
|
|
133
|
+
{
|
|
134
|
+
Transform controller = safeArea.Find("ReplayController");
|
|
135
|
+
ControllerObject = controller != null ? controller.gameObject : null;
|
|
136
|
+
Controller = ControllerObject != null ? ControllerObject.GetComponent<ReplayController>() : null;
|
|
137
|
+
if (ControllerObject == null) CreateController((RectTransform)safeArea);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
private void CreateInputBlocker(RectTransform parent)
|
|
142
|
+
{
|
|
143
|
+
GameObject prefab = Resources.Load<GameObject>("UIPrefabs/ReplayInputBlocker");
|
|
144
|
+
InputBlocker = prefab != null
|
|
145
|
+
? Instantiate(prefab, parent, false)
|
|
146
|
+
: new GameObject("ReplayInputBlocker", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
|
|
147
|
+
|
|
148
|
+
RectTransform rect = InputBlocker.GetComponent<RectTransform>();
|
|
149
|
+
if (rect.parent == null) rect.SetParent(parent, false);
|
|
150
|
+
StretchToParent(rect);
|
|
151
|
+
|
|
152
|
+
Image image = InputBlocker.GetComponent<Image>();
|
|
153
|
+
if (image != null)
|
|
154
|
+
{
|
|
155
|
+
image.raycastTarget = true;
|
|
156
|
+
if (prefab == null) image.color = Color.clear;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private void CreateController(RectTransform parent)
|
|
161
|
+
{
|
|
162
|
+
GameObject prefab = Resources.Load<GameObject>("UIPrefabs/ReplayController");
|
|
163
|
+
if (prefab == null)
|
|
164
|
+
{
|
|
165
|
+
Debug.LogWarning("[ReplayPresentationCanvas] ReplayController prefab not found.");
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
ControllerObject = Instantiate(prefab, parent, false);
|
|
170
|
+
ControllerObject.transform.SetAsLastSibling();
|
|
171
|
+
Controller = ControllerObject.GetComponent<ReplayController>();
|
|
172
|
+
if (Controller == null) Controller = ControllerObject.AddComponent<ReplayController>();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private static void StretchToParent(RectTransform rect)
|
|
176
|
+
{
|
|
177
|
+
rect.anchorMin = Vector2.zero;
|
|
178
|
+
rect.anchorMax = Vector2.one;
|
|
179
|
+
rect.offsetMin = Vector2.zero;
|
|
180
|
+
rect.offsetMax = Vector2.zero;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
@@ -90,6 +90,12 @@ namespace Hyper.Internal
|
|
|
90
90
|
retryTimerText.text = $"00:0{5 - HyperRuntime.BackendManager.CurrentRetryCount}";
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
internal void ShowRetryCountdown(int secondsRemaining)
|
|
94
|
+
{
|
|
95
|
+
DisableAllCTAButtons();
|
|
96
|
+
retryTimerText.text = $"00:{Mathf.Max(0, secondsRemaining):00}";
|
|
97
|
+
}
|
|
98
|
+
|
|
93
99
|
private void EnableRetryLaterButton()
|
|
94
100
|
{
|
|
95
101
|
ctaButtonsHolder.interactable = true;
|
|
@@ -115,6 +121,12 @@ namespace Hyper.Internal
|
|
|
115
121
|
|
|
116
122
|
public void Retry() // On Retry Button Clicked
|
|
117
123
|
{
|
|
124
|
+
if (_gameManager.IsReplayMode)
|
|
125
|
+
{
|
|
126
|
+
_gameManager.RetryReplayLoading();
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
118
130
|
StartReconnectionCoroutine();
|
|
119
131
|
}
|
|
120
132
|
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
using Hyper.Shared;
|
|
2
|
+
using UnityEngine;
|
|
3
|
+
using UnityEngine.UI;
|
|
4
|
+
|
|
5
|
+
namespace Hyper.Internal
|
|
6
|
+
{
|
|
7
|
+
internal sealed class ReplayOverModal : MonoBehaviour
|
|
8
|
+
{
|
|
9
|
+
[SerializeField] private Button watchAgainButton;
|
|
10
|
+
[SerializeField] private Button exitButton;
|
|
11
|
+
private bool _handled;
|
|
12
|
+
|
|
13
|
+
private void Awake()
|
|
14
|
+
{
|
|
15
|
+
Button[] buttons = GetComponentsInChildren<Button>(true);
|
|
16
|
+
for (int i = 0; i < buttons.Length; i++)
|
|
17
|
+
{
|
|
18
|
+
if (buttons[i].name == "Watch Again") watchAgainButton = buttons[i];
|
|
19
|
+
else if (buttons[i].name == "Exit") exitButton = buttons[i];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (watchAgainButton != null) watchAgainButton.onClick.AddListener(WatchAgain);
|
|
23
|
+
if (exitButton != null) exitButton.onClick.AddListener(Exit);
|
|
24
|
+
}
|
|
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
|
+
|
|
33
|
+
private void OnDestroy()
|
|
34
|
+
{
|
|
35
|
+
if (watchAgainButton != null) watchAgainButton.onClick.RemoveListener(WatchAgain);
|
|
36
|
+
if (exitButton != null) exitButton.onClick.RemoveListener(Exit);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private void WatchAgain()
|
|
40
|
+
{
|
|
41
|
+
if (_handled) return;
|
|
42
|
+
_handled = true;
|
|
43
|
+
DisableButtons();
|
|
44
|
+
HyperRuntime.RestartReplaySession();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private void Exit()
|
|
48
|
+
{
|
|
49
|
+
if (_handled) return;
|
|
50
|
+
_handled = true;
|
|
51
|
+
DisableButtons();
|
|
52
|
+
HyperRuntime.GameManager?.ExitCompletedReplay();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private void DisableButtons()
|
|
56
|
+
{
|
|
57
|
+
if (watchAgainButton != null) watchAgainButton.interactable = false;
|
|
58
|
+
if (exitButton != null) exitButton.interactable = false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
using System.Collections;
|
|
2
|
-
using System.Runtime.InteropServices;
|
|
3
2
|
using Hyper.Internal.Managers;
|
|
4
3
|
using Hyper.Shared;
|
|
5
4
|
using TMPro;
|
|
6
5
|
using UnityEngine;
|
|
7
|
-
using UnityEngine.SceneManagement;
|
|
8
6
|
using UnityEngine.UI;
|
|
9
7
|
|
|
10
8
|
namespace Hyper.Internal
|
|
@@ -12,38 +10,61 @@ namespace Hyper.Internal
|
|
|
12
10
|
internal class StartingInstructionModal : MonoBehaviour
|
|
13
11
|
{
|
|
14
12
|
|
|
15
|
-
#if UNITY_WEBGL
|
|
16
|
-
[DllImport("__Internal")]
|
|
17
|
-
private static extern void MarkGameStartedOnHTML();
|
|
18
|
-
#endif
|
|
19
13
|
[SerializeField] private TextMeshProUGUI startCtaLabel;
|
|
20
14
|
[SerializeField] private BlinkingText blinkingText;
|
|
21
15
|
[SerializeField] private RectTransform swipeGif;
|
|
22
16
|
[SerializeField] private RectTransform handSpriteInGif;
|
|
23
|
-
private
|
|
24
|
-
private DataManager _dataManager;
|
|
17
|
+
[SerializeField] private float replayAutoStartDelay = 1f;
|
|
25
18
|
private GameManager _gameManager;
|
|
26
|
-
private BackendManager _backendManager;
|
|
27
19
|
private StartCTA _currentCTA;
|
|
28
20
|
private SwipeDirection _swipeDirection;
|
|
29
21
|
|
|
30
22
|
private bool _canAcceptInput = false;
|
|
31
23
|
private Vector2 _swipeStartPosition;
|
|
32
24
|
private bool _isTrackingSwipe;
|
|
25
|
+
private bool _hasStarted;
|
|
26
|
+
private Coroutine _replayAutoStartCoroutine;
|
|
33
27
|
private const float SWIPE_THRESHOLD = 50f;
|
|
34
28
|
|
|
35
29
|
void Awake()
|
|
36
30
|
{
|
|
37
|
-
_dataManager = HyperRuntime.DataManager;
|
|
38
|
-
_eventManager = HyperRuntime.EventManager;
|
|
39
31
|
_gameManager = HyperRuntime.GameManager;
|
|
40
|
-
_backendManager = HyperRuntime.BackendManager;
|
|
41
32
|
}
|
|
42
33
|
|
|
43
34
|
void OnEnable()
|
|
44
35
|
{
|
|
45
36
|
_canAcceptInput = false;
|
|
46
|
-
|
|
37
|
+
_hasStarted = false;
|
|
38
|
+
|
|
39
|
+
if (HyperRuntime.GameManager != null && HyperRuntime.GameManager.IsReplayMode)
|
|
40
|
+
{
|
|
41
|
+
_replayAutoStartCoroutine = StartCoroutine(AutoStartReplay());
|
|
42
|
+
}
|
|
43
|
+
else
|
|
44
|
+
{
|
|
45
|
+
StartCoroutine(EnableInputAfterDelay());
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private void OnDisable()
|
|
50
|
+
{
|
|
51
|
+
if (_replayAutoStartCoroutine != null)
|
|
52
|
+
{
|
|
53
|
+
StopCoroutine(_replayAutoStartCoroutine);
|
|
54
|
+
_replayAutoStartCoroutine = null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private IEnumerator AutoStartReplay()
|
|
59
|
+
{
|
|
60
|
+
float elapsed = 0f;
|
|
61
|
+
float delay = Mathf.Max(0f, replayAutoStartDelay);
|
|
62
|
+
while (elapsed < delay)
|
|
63
|
+
{
|
|
64
|
+
if (Application.isFocused) elapsed += Time.unscaledDeltaTime;
|
|
65
|
+
yield return null;
|
|
66
|
+
}
|
|
67
|
+
StartGame();
|
|
47
68
|
}
|
|
48
69
|
|
|
49
70
|
private IEnumerator EnableInputAfterDelay()
|
|
@@ -59,6 +80,7 @@ namespace Hyper.Internal
|
|
|
59
80
|
|
|
60
81
|
void Update()
|
|
61
82
|
{
|
|
83
|
+
if (HyperRuntime.GameManager != null && HyperRuntime.GameManager.IsReplayMode) return;
|
|
62
84
|
if (!gameObject.activeSelf || !_canAcceptInput) return;
|
|
63
85
|
|
|
64
86
|
if (_currentCTA == StartCTA.TapToPlay)
|
|
@@ -279,23 +301,10 @@ namespace Hyper.Internal
|
|
|
279
301
|
/// </summary>
|
|
280
302
|
private void StartGame()
|
|
281
303
|
{
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
HyperRuntime.Timer.StartActiveGameTimer();
|
|
304
|
+
if (_hasStarted) return;
|
|
305
|
+
_hasStarted = true;
|
|
285
306
|
|
|
286
|
-
|
|
287
|
-
_backendManager.StartSendingScores(); // Sender loop already pauses actual submissions while disconnected or token-gated.
|
|
288
|
-
|
|
289
|
-
// startGame handshake can only be emitted when socket is connected.
|
|
290
|
-
if (_backendManager.isSocketConnected)
|
|
291
|
-
{
|
|
292
|
-
_backendManager.SendGameStarted();
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
#if UNITY_WEBGL && !UNITY_EDITOR
|
|
296
|
-
MarkGameStartedOnHTML();
|
|
297
|
-
#endif
|
|
298
|
-
_eventManager.InvokeGameStartEvent();
|
|
307
|
+
_gameManager.StartGameplay();
|
|
299
308
|
gameObject.SetActive(false);
|
|
300
309
|
}
|
|
301
310
|
|