app.hypergames.hypersdk 1.8.21 → 1.8.23

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.
Files changed (34) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/Runtime/Internal/Bootstrap/HyperLoader.cs +4 -1
  3. package/Runtime/Internal/Managers/BackendManager.cs +132 -19
  4. package/Runtime/Internal/Managers/GameManager.cs +107 -9
  5. package/Runtime/Internal/ScriptableObjects/HyperSDKSettings.cs +1 -1
  6. package/Runtime/Internal/UI/Modals/TutorialAnnouncementModal.cs +57 -0
  7. package/Runtime/Internal/UI/Modals/TutorialAnnouncementModal.cs.meta +2 -0
  8. package/Runtime/Plugins/WebGL/HyperTutorialCachePlugin.jslib +5 -1
  9. package/Runtime/Resources/Sprites/Frame 2147224037.png +0 -0
  10. package/Runtime/Resources/Sprites/{TutorialModal/P Container.png.meta → Frame 2147224037.png.meta } +12 -25
  11. package/Runtime/Resources/UIPrefabs/ConnectionStatusBar.prefab +10 -10
  12. package/Runtime/Resources/UIPrefabs/GameOverModal_Battle.prefab +1 -1
  13. package/Runtime/Resources/UIPrefabs/GameOverModal_Practice.prefab +1 -1
  14. package/Runtime/Resources/UIPrefabs/GamePausedModal_Battle.prefab +1 -1
  15. package/Runtime/Resources/UIPrefabs/GamePausedModal_Battle_Landscape.prefab +1 -1
  16. package/Runtime/Resources/UIPrefabs/GamePausedModal_Practice.prefab +12 -0
  17. package/Runtime/Resources/UIPrefabs/LoadingFailedModal.prefab +7 -7
  18. package/Runtime/Resources/UIPrefabs/ScoreSubmissionFailedModal_Portrait.prefab +1 -1
  19. package/Runtime/Resources/UIPrefabs/TutorialAnnouncementModal.prefab +699 -0
  20. package/Runtime/Resources/UIPrefabs/TutorialAnnouncementModal.prefab.meta +7 -0
  21. package/Runtime/Resources/UIPrefabs/TutorialLandscapeModal.prefab +2 -2
  22. package/Runtime/Resources/UIPrefabs/TutorialPortraitModal.prefab +1 -1
  23. package/package.json +1 -1
  24. package/Runtime/Resources/Sprites/TutorialModal/L Container.png +0 -0
  25. package/Runtime/Resources/Sprites/TutorialModal/L Container.png.meta +0 -169
  26. package/Runtime/Resources/Sprites/TutorialModal/P Container.png +0 -0
  27. package/Runtime/Resources/Sprites/TutorialModal/Time_Seeker_Bar_Empty.png +0 -0
  28. package/Runtime/Resources/Sprites/TutorialModal/Time_Seeker_Bar_Empty.png.meta +0 -156
  29. package/Runtime/Resources/Sprites/TutorialModal/Time_Seeker_Bar_Filled.png +0 -0
  30. package/Runtime/Resources/Sprites/TutorialModal/Time_Seeker_Bar_Filled.png.meta +0 -156
  31. package/Runtime/Resources/Sprites/TutorialModal/Tutorial_Background_Landscape.png +0 -0
  32. package/Runtime/Resources/Sprites/TutorialModal/Tutorial_Background_Landscape.png.meta +0 -169
  33. package/Runtime/Resources/Sprites/TutorialModal/Tutorial_Background_Portrait.png +0 -0
  34. package/Runtime/Resources/Sprites/TutorialModal/Tutorial_Background_Portrait.png.meta +0 -169
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [1.8.23](https://github.com/mvmhyper/hyper-sdk/compare/v1.8.22...v1.8.23) (2026-07-08)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * signal tutorial availability before cache completes ([7a8d043](https://github.com/mvmhyper/hyper-sdk/commit/7a8d043e016c36007b088535f06ae5f4bb4ae64d))
7
+
8
+ ## [1.8.22](https://github.com/mvmhyper/hyper-sdk/compare/v1.8.21...v1.8.22) (2026-07-08)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * add tutorial announcement prompt ([0b5e009](https://github.com/mvmhyper/hyper-sdk/commit/0b5e0099346d144b56d35a39d613e24a776ef11b))
14
+
1
15
  ## [1.8.21](https://github.com/mvmhyper/hyper-sdk/compare/v1.8.20...v1.8.21) (2026-07-08)
2
16
 
3
17
 
@@ -263,6 +263,9 @@ namespace Hyper.Internal
263
263
  _bootstrapProgress = _progressAfterInit;
264
264
  _loadingBarSlider.value = _bootstrapProgress;
265
265
 
266
+ // Start tutorial discovery early, but never wait for it before loading gameplay.
267
+ HyperRuntime.BackendManager.GetTutorial(null);
268
+
266
269
  // Step 2: Handle Backend/PVP or Practice mode initialization
267
270
  if (_gameManager.Config.IsBackendGame && _gameManager.Config.isPVP)
268
271
  {
@@ -475,4 +478,4 @@ namespace Hyper.Internal
475
478
 
476
479
  #endregion
477
480
  }
478
- }
481
+ }
@@ -49,7 +49,8 @@ namespace Hyper.Internal.Managers
49
49
  public bool isSocketConnected { get; private set; }
50
50
  public bool tutorialFetchSuccess { get; private set; }
51
51
  public bool tutorialExistsButFailed { get; private set; }
52
- public bool tutorialDoesNotExist => !tutorialExistsButFailed && !tutorialFetchSuccess && !_isFetchingTutorial;
52
+ public bool tutorialDoesNotExist => TutorialAvailability == TutorialAvailabilityState.Unavailable;
53
+ public TutorialAvailabilityState TutorialAvailability { get; private set; } = TutorialAvailabilityState.Unknown;
53
54
 
54
55
  /// <summary>
55
56
  /// Type of error that occurred during score submission.
@@ -127,7 +128,7 @@ namespace Hyper.Internal.Managers
127
128
  private void FetchAndCacheTutorials(string serverBaseUrl, string gameSlug, string gameObject)
128
129
  {
129
130
  _isFetchingTutorial = false;
130
- _onTutorialSuccess?.Invoke();
131
+ OnTutorialCacheComplete("success");
131
132
  }
132
133
 
133
134
  private void InitWebSocket(string serverUrl) { }
@@ -1587,27 +1588,41 @@ namespace Hyper.Internal.Managers
1587
1588
  NetworkError
1588
1589
  }
1589
1590
 
1590
- private Action _onFetchComplete;
1591
- private Action _onTutorialSuccess;
1592
- private Action<TutorialFetchStatus> _onTutorialFailure;
1591
+ public enum TutorialAvailabilityState
1592
+ {
1593
+ Unknown,
1594
+ InProgress,
1595
+ Available,
1596
+ Unavailable,
1597
+ ExistsButFailed
1598
+ }
1599
+
1600
+ private readonly List<Action> _fetchCompleteCallbacks = new List<Action>();
1601
+ private readonly List<Action> _tutorialSuccessCallbacks = new List<Action>();
1602
+ private readonly List<Action<TutorialFetchStatus>> _tutorialFailureCallbacks = new List<Action<TutorialFetchStatus>>();
1593
1603
  private bool _isFetchingTutorial;
1594
1604
 
1595
1605
  public void GetTutorial(Action fetchComplete, Action onSuccess = null, Action<TutorialFetchStatus> onFailure = null)
1596
1606
  {
1597
1607
  if (_gameManager == null) _gameManager = HyperRuntime.GameManager;
1598
1608
 
1609
+ if (IsTutorialFetchComplete())
1610
+ {
1611
+ InvokeTutorialCallbacksForCurrentState(fetchComplete, onSuccess, onFailure);
1612
+ return;
1613
+ }
1614
+
1615
+ AddTutorialCallbacks(fetchComplete, onSuccess, onFailure);
1616
+
1599
1617
  if (_isFetchingTutorial)
1600
1618
  {
1601
- HyperDebug.LogWarning("Tutorial fetch already in progress");
1602
1619
  return;
1603
1620
  }
1604
1621
 
1605
- _onFetchComplete = fetchComplete;
1606
- _onTutorialSuccess = onSuccess;
1607
- _onTutorialFailure = onFailure;
1608
1622
  _currentRetryCount = 0;
1609
1623
  tutorialExistsButFailed = false;
1610
1624
  tutorialFetchSuccess = false;
1625
+ TutorialAvailability = TutorialAvailabilityState.InProgress;
1611
1626
  TryFetchTutorial();
1612
1627
  }
1613
1628
 
@@ -1618,30 +1633,38 @@ namespace Hyper.Internal.Managers
1618
1633
 
1619
1634
  #if UNITY_WEBGL && !UNITY_EDITOR
1620
1635
  FetchAndCacheTutorials(GetServerUrl(), gameSlug, gameObject.name);
1621
- #else
1636
+ #elif UNITY_EDITOR
1622
1637
  StartCoroutine(SimulateTutorialFetch());
1638
+ #else
1639
+ OnTutorialCacheComplete("fetch_failed");
1623
1640
  #endif
1624
1641
  }
1625
1642
 
1626
1643
  public void OnTutorialCacheComplete(string result)
1627
1644
  {
1628
- _onFetchComplete?.Invoke();
1629
-
1630
1645
  switch (result)
1631
1646
  {
1647
+ case "available":
1648
+ tutorialExistsButFailed = false;
1649
+ tutorialFetchSuccess = false;
1650
+ TutorialAvailability = TutorialAvailabilityState.Available;
1651
+ break;
1652
+
1632
1653
  case "success":
1633
- _eventManager?.InvokeTutorialFetchCompleteEvent();
1634
1654
  _isFetchingTutorial = false;
1635
1655
  tutorialExistsButFailed = false;
1636
1656
  tutorialFetchSuccess = true;
1637
- _onTutorialSuccess?.Invoke();
1657
+ TutorialAvailability = TutorialAvailabilityState.Available;
1658
+ _eventManager?.InvokeTutorialFetchCompleteEvent();
1659
+ InvokeAndClearTutorialCallbacks(TutorialFetchStatus.Success);
1638
1660
  break;
1639
1661
 
1640
1662
  case "no_tutorial":
1641
1663
  _isFetchingTutorial = false;
1642
1664
  tutorialExistsButFailed = false;
1643
1665
  tutorialFetchSuccess = false;
1644
- _onTutorialFailure?.Invoke(TutorialFetchStatus.NoTutorialExists);
1666
+ TutorialAvailability = TutorialAvailabilityState.Unavailable;
1667
+ InvokeAndClearTutorialCallbacks(TutorialFetchStatus.NoTutorialExists);
1645
1668
  _eventManager?.InvokeTutorialNotExistsEvent();
1646
1669
  break;
1647
1670
 
@@ -1659,16 +1682,106 @@ namespace Hyper.Internal.Managers
1659
1682
 
1660
1683
  private void HandleRetryOrFail(TutorialFetchStatus status)
1661
1684
  {
1662
- _onTutorialFailure?.Invoke(status);
1663
- _eventManager?.InvokeTutorialFetchFailedEvent();
1664
1685
  _isFetchingTutorial = false;
1686
+
1687
+ if (status == TutorialFetchStatus.DownloadFailed)
1688
+ {
1689
+ tutorialExistsButFailed = true;
1690
+ tutorialFetchSuccess = false;
1691
+ TutorialAvailability = TutorialAvailabilityState.ExistsButFailed;
1692
+ }
1693
+ else
1694
+ {
1695
+ tutorialExistsButFailed = false;
1696
+ tutorialFetchSuccess = false;
1697
+ TutorialAvailability = TutorialAvailabilityState.Unknown;
1698
+ }
1699
+
1700
+ InvokeAndClearTutorialCallbacks(status);
1701
+ _eventManager?.InvokeTutorialFetchFailedEvent();
1702
+ }
1703
+
1704
+ private bool IsTutorialFetchComplete()
1705
+ {
1706
+ return (TutorialAvailability == TutorialAvailabilityState.Available && !_isFetchingTutorial) ||
1707
+ TutorialAvailability == TutorialAvailabilityState.Unavailable;
1708
+ }
1709
+
1710
+ private void AddTutorialCallbacks(Action fetchComplete, Action onSuccess, Action<TutorialFetchStatus> onFailure)
1711
+ {
1712
+ if (fetchComplete != null) _fetchCompleteCallbacks.Add(fetchComplete);
1713
+ if (onSuccess != null) _tutorialSuccessCallbacks.Add(onSuccess);
1714
+ if (onFailure != null) _tutorialFailureCallbacks.Add(onFailure);
1715
+ }
1716
+
1717
+ private void InvokeTutorialCallbacksForCurrentState(Action fetchComplete, Action onSuccess, Action<TutorialFetchStatus> onFailure)
1718
+ {
1719
+ switch (TutorialAvailability)
1720
+ {
1721
+ case TutorialAvailabilityState.Available:
1722
+ onSuccess?.Invoke();
1723
+ break;
1724
+ case TutorialAvailabilityState.Unavailable:
1725
+ onFailure?.Invoke(TutorialFetchStatus.NoTutorialExists);
1726
+ break;
1727
+ case TutorialAvailabilityState.ExistsButFailed:
1728
+ onFailure?.Invoke(TutorialFetchStatus.DownloadFailed);
1729
+ break;
1730
+ }
1731
+
1732
+ fetchComplete?.Invoke();
1733
+ }
1734
+
1735
+ private void InvokeAndClearTutorialCallbacks(TutorialFetchStatus status)
1736
+ {
1737
+ if (status == TutorialFetchStatus.Success)
1738
+ {
1739
+ for (int i = 0; i < _tutorialSuccessCallbacks.Count; i++)
1740
+ {
1741
+ _tutorialSuccessCallbacks[i]?.Invoke();
1742
+ }
1743
+ }
1744
+ else
1745
+ {
1746
+ for (int i = 0; i < _tutorialFailureCallbacks.Count; i++)
1747
+ {
1748
+ _tutorialFailureCallbacks[i]?.Invoke(status);
1749
+ }
1750
+ }
1751
+
1752
+ for (int i = 0; i < _fetchCompleteCallbacks.Count; i++)
1753
+ {
1754
+ _fetchCompleteCallbacks[i]?.Invoke();
1755
+ }
1756
+
1757
+ _fetchCompleteCallbacks.Clear();
1758
+ _tutorialSuccessCallbacks.Clear();
1759
+ _tutorialFailureCallbacks.Clear();
1665
1760
  }
1666
1761
 
1667
1762
  #if UNITY_EDITOR
1668
1763
  private IEnumerator SimulateTutorialFetch()
1669
1764
  {
1670
- yield return new WaitForSecondsRealtime(1.5f);
1671
- OnTutorialCacheComplete(UnityEngine.Random.value > 0.5f ? "no_tutorial" : "download_failed");
1765
+ var value = UnityEngine.Random.Range(0, 4);
1766
+ Debug.Log($"[Tutorial] Simulating tutorial fetch result: {value}");
1767
+
1768
+ switch (value)
1769
+ {
1770
+ case 0:
1771
+ OnTutorialCacheComplete("success");
1772
+ break;
1773
+ case 1:
1774
+ OnTutorialCacheComplete("download_failed");
1775
+ break;
1776
+ case 2:
1777
+ OnTutorialCacheComplete("fetch_failed");
1778
+ break;
1779
+ default:
1780
+ OnTutorialCacheComplete("no_tutorial");
1781
+ break;
1782
+ }
1783
+
1784
+ yield break;
1672
1785
  }
1673
1786
  #endif
1674
1787
 
@@ -805,20 +805,13 @@ namespace Hyper.Internal.Managers
805
805
 
806
806
  ShowControlBarElements();
807
807
  AddTutorialModal();
808
- ShowStartingInstructionModal();
808
+ ShowTutorialAnnouncementOrStartingInstruction();
809
809
  }
810
810
 
811
811
  private IEnumerator BootstrapAndStart()
812
812
  {
813
813
  HyperRuntime.EventManager.OnGameStart += HandleGameStarted;
814
-
815
- bool tutorialDone = false;
816
- HyperRuntime.BackendManager.GetTutorial(() => tutorialDone = true);
817
-
818
- while (!tutorialDone)
819
- {
820
- yield return null;
821
- }
814
+ yield break;
822
815
  }
823
816
 
824
817
  private void HandleGameStarted()
@@ -978,6 +971,7 @@ namespace Hyper.Internal.Managers
978
971
  private GameObject _battleGameOverModal;
979
972
  private GameObject _practiceGameOverModal;
980
973
  private GameObject _startingInstructionModal;
974
+ private GameObject _tutorialAnnouncementModal;
981
975
  private GameObject _tutorialPortraitModal;
982
976
  private GameObject _tutorialLandscapeModal;
983
977
  private GameObject _controlBarElements;
@@ -987,6 +981,7 @@ namespace Hyper.Internal.Managers
987
981
  private GameOverModal _gameOverModalComponent;
988
982
  private ControlBar _controlBarModal;
989
983
  private TutorialModal _tutorialModalComponent;
984
+ private TutorialAnnouncementModal _tutorialAnnouncementModalComponent;
990
985
  private ScoreSubmissionFailedModal _scoreSubmissionFailedModalComponent;
991
986
  private StartingInstructionModal _startingInstructionModalComponent;
992
987
 
@@ -1495,6 +1490,109 @@ namespace Hyper.Internal.Managers
1495
1490
  SetBlockerActive(false);
1496
1491
  }
1497
1492
 
1493
+ private void ShowTutorialAnnouncementOrStartingInstruction()
1494
+ {
1495
+ if (ShouldShowTutorialAnnouncement())
1496
+ {
1497
+ ShowTutorialAnnouncementModal();
1498
+ return;
1499
+ }
1500
+
1501
+ ShowStartingInstructionModal();
1502
+ }
1503
+
1504
+ private bool ShouldShowTutorialAnnouncement()
1505
+ {
1506
+ var availability = HyperRuntime.BackendManager.TutorialAvailability;
1507
+ bool tutorialKnownToExist =
1508
+ availability == BackendManager.TutorialAvailabilityState.Available ||
1509
+ availability == BackendManager.TutorialAvailabilityState.ExistsButFailed;
1510
+
1511
+ return tutorialKnownToExist && !HasSeenTutorialAnnouncement();
1512
+ }
1513
+
1514
+ private bool HasSeenTutorialAnnouncement()
1515
+ {
1516
+ string key = GetTutorialAnnouncementSeenKey();
1517
+ return !string.IsNullOrEmpty(key) && PlayerPrefs.GetInt(key, 0) == 1;
1518
+ }
1519
+
1520
+ private void MarkTutorialAnnouncementSeen()
1521
+ {
1522
+ string key = GetTutorialAnnouncementSeenKey();
1523
+ if (string.IsNullOrEmpty(key)) return;
1524
+
1525
+ PlayerPrefs.SetInt(key, 1);
1526
+ PlayerPrefs.Save();
1527
+ }
1528
+
1529
+ private string GetTutorialAnnouncementSeenKey()
1530
+ {
1531
+ string gameIdentifier = Config != null ? Config.GameSlug : null;
1532
+
1533
+ #if UNITY_EDITOR
1534
+ if (string.IsNullOrWhiteSpace(gameIdentifier))
1535
+ {
1536
+ gameIdentifier = Application.productName;
1537
+ }
1538
+ #endif
1539
+
1540
+ if (string.IsNullOrWhiteSpace(gameIdentifier))
1541
+ {
1542
+ gameIdentifier = HyperRuntime.GameContent != null
1543
+ ? HyperRuntime.GameContent.GameScene?.SceneName
1544
+ : null;
1545
+ }
1546
+
1547
+ return string.IsNullOrWhiteSpace(gameIdentifier)
1548
+ ? null
1549
+ : $"{gameIdentifier}_sdkTutorialPromptSeen";
1550
+ }
1551
+
1552
+ private void ShowTutorialAnnouncementModal()
1553
+ {
1554
+ EnsureTutorialAnnouncementModal();
1555
+
1556
+ if (_tutorialAnnouncementModalComponent == null)
1557
+ {
1558
+ ShowStartingInstructionModal();
1559
+ return;
1560
+ }
1561
+
1562
+ _tutorialAnnouncementModalComponent.Show(() =>
1563
+ {
1564
+ MarkTutorialAnnouncementSeen();
1565
+ SetBlockerActive(false);
1566
+ ShowStartingInstructionModal();
1567
+ });
1568
+
1569
+ SetBlockerActive(true);
1570
+ }
1571
+
1572
+ private void EnsureTutorialAnnouncementModal()
1573
+ {
1574
+ if (_tutorialAnnouncementModal != null)
1575
+ {
1576
+ _tutorialAnnouncementModal.SetActive(true);
1577
+ return;
1578
+ }
1579
+
1580
+ if (_canvas == null) CreateCanvas();
1581
+
1582
+ GameObject prefab = Resources.Load<GameObject>("UIPrefabs/TutorialAnnouncementModal");
1583
+ if (prefab == null)
1584
+ {
1585
+ HyperDebug.LogWarning("[GameManager] TutorialAnnouncementModal prefab not found.");
1586
+ return;
1587
+ }
1588
+
1589
+ GameObject instance = Instantiate(prefab);
1590
+ instance.transform.SetParent(_safeArea.transform, false);
1591
+
1592
+ _tutorialAnnouncementModal = instance;
1593
+ _tutorialAnnouncementModalComponent = instance.GetComponent<TutorialAnnouncementModal>();
1594
+ }
1595
+
1498
1596
  private void EnsureStartingInstructionModal()
1499
1597
  {
1500
1598
  if (_startingInstructionModal != null)
@@ -95,4 +95,4 @@ namespace Hyper.Internal
95
95
 
96
96
  #endregion
97
97
  }
98
- }
98
+ }
@@ -0,0 +1,57 @@
1
+ using UnityEngine;
2
+ using UnityEngine.UI;
3
+
4
+ namespace Hyper.Internal
5
+ {
6
+ internal class TutorialAnnouncementModal : MonoBehaviour
7
+ {
8
+ [SerializeField] private Button closeButton;
9
+
10
+ private System.Action _onClosed;
11
+ private bool _hasClosed;
12
+
13
+ private void Awake()
14
+ {
15
+ if (closeButton == null)
16
+ {
17
+ closeButton = GetComponentInChildren<Button>(true);
18
+ }
19
+
20
+ if (closeButton != null)
21
+ {
22
+ closeButton.onClick.AddListener(HandleCloseClicked);
23
+ }
24
+ else
25
+ {
26
+ HyperDebug.LogWarning("[TutorialAnnouncementModal] Close button is not assigned.");
27
+ }
28
+ }
29
+
30
+ private void OnDestroy()
31
+ {
32
+ if (closeButton != null)
33
+ {
34
+ closeButton.onClick.RemoveListener(HandleCloseClicked);
35
+ }
36
+ }
37
+
38
+ internal void Show(System.Action onClosed)
39
+ {
40
+ _onClosed = onClosed;
41
+ _hasClosed = false;
42
+ gameObject.SetActive(true);
43
+ }
44
+
45
+ private void HandleCloseClicked()
46
+ {
47
+ if (_hasClosed) return;
48
+
49
+ _hasClosed = true;
50
+ gameObject.SetActive(false);
51
+
52
+ System.Action onClosed = _onClosed;
53
+ _onClosed = null;
54
+ onClosed?.Invoke();
55
+ }
56
+ }
57
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: ebbcf84b3f3cc354b8072846a794168a
@@ -8,6 +8,7 @@ mergeInto(LibraryManager.library, {
8
8
  const gameObject = UTF8ToString(gameObjectPtr);
9
9
 
10
10
  const endpoint = `${baseUrl}/games/${gameSlug}/tutorials`;
11
+ let tutorialRecordsFound = false;
11
12
 
12
13
  caches.open("tutorial-cache").then(async (cache) => {
13
14
  try {
@@ -22,6 +23,9 @@ mergeInto(LibraryManager.library, {
22
23
  return;
23
24
  }
24
25
 
26
+ tutorialRecordsFound = true;
27
+ SendMessage(gameObject, "OnTutorialCacheComplete", "available");
28
+
25
29
  const cards = records
26
30
  .filter(r => r && r.fileUrl)
27
31
  .map((record, index) => ({
@@ -48,7 +52,7 @@ mergeInto(LibraryManager.library, {
48
52
  SendMessage(gameObject, "OnTutorialCacheComplete", "success");
49
53
  } catch (e) {
50
54
  console.error("Tutorial caching error:", e);
51
- const status = e.message.includes("Download failed") ? "download_failed" : "fetch_failed";
55
+ const status = tutorialRecordsFound || e.message.includes("Download failed") ? "download_failed" : "fetch_failed";
52
56
  SendMessage(gameObject, "OnTutorialCacheComplete", status);
53
57
  }
54
58
  });
@@ -1,10 +1,10 @@
1
1
  fileFormatVersion: 2
2
- guid: b460fc5e54cc5dd45b365f0fb7aa23ca
2
+ guid: 79ea1f5df2417914697380a19c4438fc
3
3
  TextureImporter:
4
4
  internalIDToNameTable:
5
5
  - first:
6
- 213: -1217429407066048564
7
- second: P Container_0
6
+ 213: 4044033671516185218
7
+ second: Frame 2147224037_0
8
8
  externalObjects: {}
9
9
  serializedVersion: 13
10
10
  mipmaps:
@@ -53,7 +53,7 @@ TextureImporter:
53
53
  spritePivot: {x: 0.5, y: 0.5}
54
54
  spritePixelsToUnits: 100
55
55
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
56
- spriteGenerateFallbackPhysicsShape: 1
56
+ spriteGenerateFallbackPhysicsShape: 0
57
57
  alphaUsage: 1
58
58
  alphaIsTransparency: 1
59
59
  spriteTessellationDetail: -1
@@ -72,11 +72,11 @@ TextureImporter:
72
72
  platformSettings:
73
73
  - serializedVersion: 4
74
74
  buildTarget: DefaultTexturePlatform
75
- maxTextureSize: 2048
75
+ maxTextureSize: 1024
76
76
  resizeAlgorithm: 0
77
77
  textureFormat: -1
78
78
  textureCompression: 1
79
- compressionQuality: 45
79
+ compressionQuality: 50
80
80
  crunchedCompression: 1
81
81
  allowsAlphaSplitting: 0
82
82
  overridden: 0
@@ -96,19 +96,6 @@ TextureImporter:
96
96
  ignorePlatformSupport: 0
97
97
  androidETC2FallbackOverride: 0
98
98
  forceMaximumCompressionQuality_BC6H_BC7: 0
99
- - serializedVersion: 4
100
- buildTarget: Android
101
- maxTextureSize: 2048
102
- resizeAlgorithm: 0
103
- textureFormat: -1
104
- textureCompression: 1
105
- compressionQuality: 50
106
- crunchedCompression: 0
107
- allowsAlphaSplitting: 0
108
- overridden: 0
109
- ignorePlatformSupport: 0
110
- androidETC2FallbackOverride: 0
111
- forceMaximumCompressionQuality_BC6H_BC7: 0
112
99
  - serializedVersion: 4
113
100
  buildTarget: WebGL
114
101
  maxTextureSize: 2048
@@ -126,13 +113,13 @@ TextureImporter:
126
113
  serializedVersion: 2
127
114
  sprites:
128
115
  - serializedVersion: 2
129
- name: P Container_0
116
+ name: Frame 2147224037_0
130
117
  rect:
131
118
  serializedVersion: 2
132
119
  x: 0
133
120
  y: 0
134
- width: 516
135
- height: 920
121
+ width: 1180
122
+ height: 808
136
123
  alignment: 0
137
124
  pivot: {x: 0, y: 0}
138
125
  border: {x: 0, y: 0, z: 0, w: 0}
@@ -141,8 +128,8 @@ TextureImporter:
141
128
  physicsShape: []
142
129
  tessellationDetail: -1
143
130
  bones: []
144
- spriteID: cc7b6bc8762da1fe0800000000000000
145
- internalID: -1217429407066048564
131
+ spriteID: 282e072b23b4f1830800000000000000
132
+ internalID: 4044033671516185218
146
133
  vertices: []
147
134
  indices:
148
135
  edges: []
@@ -161,7 +148,7 @@ TextureImporter:
161
148
  spriteCustomMetadata:
162
149
  entries: []
163
150
  nameFileIdTable:
164
- P Container_0: -1217429407066048564
151
+ Frame 2147224037_0: 4044033671516185218
165
152
  mipmapLimitGroupName:
166
153
  pSDRemoveMatte: 0
167
154
  userData:
@@ -36,7 +36,7 @@ RectTransform:
36
36
  m_AnchorMin: {x: 0.5, y: 1}
37
37
  m_AnchorMax: {x: 0.5, y: 1}
38
38
  m_AnchoredPosition: {x: 43.75238, y: -29.683838}
39
- m_SizeDelta: {x: 536.79, y: 28.8}
39
+ m_SizeDelta: {x: 536.76, y: 28.8}
40
40
  m_Pivot: {x: 0.5, y: 0.5}
41
41
  --- !u!222 &4167215372404575111
42
42
  CanvasRenderer:
@@ -228,14 +228,14 @@ RectTransform:
228
228
  m_GameObject: {fileID: 1339429102133054667}
229
229
  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
230
230
  m_LocalPosition: {x: 0, y: 0, z: 0}
231
- m_LocalScale: {x: 1.2431005, y: 1.2431005, z: 1.2431005}
232
- m_ConstrainProportionsScale: 0
231
+ m_LocalScale: {x: 1.1, y: 1.1, z: 1.1}
232
+ m_ConstrainProportionsScale: 1
233
233
  m_Children: []
234
234
  m_Father: {fileID: 3144244002372456063}
235
235
  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
236
236
  m_AnchorMin: {x: 0.5, y: 0.5}
237
237
  m_AnchorMax: {x: 0.5, y: 0.5}
238
- m_AnchoredPosition: {x: -278.74756, y: 0.000049591064}
238
+ m_AnchoredPosition: {x: -278.74756, y: 0}
239
239
  m_SizeDelta: {x: 51.5, y: 41}
240
240
  m_Pivot: {x: 0.5, y: 0.5}
241
241
  --- !u!222 &6646643930977255528
@@ -416,14 +416,14 @@ RectTransform:
416
416
  m_GameObject: {fileID: 2742868627260701116}
417
417
  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
418
418
  m_LocalPosition: {x: 0, y: 0, z: 0}
419
- m_LocalScale: {x: 1, y: 1, z: 1}
420
- m_ConstrainProportionsScale: 0
419
+ m_LocalScale: {x: 0.8, y: 0.8, z: 0.8}
420
+ m_ConstrainProportionsScale: 1
421
421
  m_Children: []
422
422
  m_Father: {fileID: 6079682807480946086}
423
423
  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
424
- m_AnchorMin: {x: 0.5, y: 1}
425
- m_AnchorMax: {x: 0.5, y: 1}
426
- m_AnchoredPosition: {x: -222.96002, y: -20.5}
424
+ m_AnchorMin: {x: 0.5, y: 0.5}
425
+ m_AnchorMax: {x: 0.5, y: 0.5}
426
+ m_AnchoredPosition: {x: -222.96002, y: 0}
427
427
  m_SizeDelta: {x: 51.5, y: 41}
428
428
  m_Pivot: {x: 0.5, y: 0.5}
429
429
  --- !u!222 &6181031279965490734
@@ -613,7 +613,7 @@ RectTransform:
613
613
  m_AnchorMin: {x: 0.5, y: 1}
614
614
  m_AnchorMax: {x: 0.5, y: 1}
615
615
  m_AnchoredPosition: {x: 42.23999, y: -23.5}
616
- m_SizeDelta: {x: 425.12, y: 28.8}
616
+ m_SizeDelta: {x: 425.1, y: 28.8}
617
617
  m_Pivot: {x: 0.5, y: 0.5}
618
618
  --- !u!222 &8979309464556769080
619
619
  CanvasRenderer:
@@ -184,7 +184,7 @@ RectTransform:
184
184
  m_GameObject: {fileID: 1641685960017025922}
185
185
  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
186
186
  m_LocalPosition: {x: 0, y: 0, z: 0}
187
- m_LocalScale: {x: 1.15, y: 1.15, z: 1.15}
187
+ m_LocalScale: {x: 1.25, y: 1.25, z: 1.25}
188
188
  m_ConstrainProportionsScale: 1
189
189
  m_Children:
190
190
  - {fileID: 6118213081617822483}
@@ -125,7 +125,7 @@ RectTransform:
125
125
  m_GameObject: {fileID: 936452418214250672}
126
126
  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
127
127
  m_LocalPosition: {x: 0, y: 0, z: 0}
128
- m_LocalScale: {x: 1.15, y: 1.15, z: 1.15}
128
+ m_LocalScale: {x: 1.25, y: 1.25, z: 1.25}
129
129
  m_ConstrainProportionsScale: 1
130
130
  m_Children:
131
131
  - {fileID: 943448477169687493}
@@ -257,7 +257,7 @@ RectTransform:
257
257
  m_GameObject: {fileID: 936452418214250672}
258
258
  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
259
259
  m_LocalPosition: {x: 0, y: 0, z: 0}
260
- m_LocalScale: {x: 1.15, y: 1.15, z: 1.15}
260
+ m_LocalScale: {x: 1.25, y: 1.25, z: 1.25}
261
261
  m_ConstrainProportionsScale: 1
262
262
  m_Children:
263
263
  - {fileID: 943448477169687493}