Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
SSBookMinigames
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
SSBookMinigames
Commits
1f5a8eb6
Commit
1f5a8eb6
authored
Apr 12, 2026
by
saad
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'NewUI' into pt_msq_opt
parents
88638ac0
2f3b6762
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
191 additions
and
82 deletions
+191
-82
AppRouter.cs
My project/Assets/App/Infrastructure/Core/AppRouter.cs
+92
-40
SupabaseManager.cs
My project/Assets/App/Infrastructure/Core/SupabaseManager.cs
+14
-14
UserService.cs
My project/Assets/App/Infrastructure/User/UserService.cs
+0
-1
HomeController.cs
My project/Assets/App/UI/HomeController.cs
+1
-0
Boot.unity
My project/Assets/AppUI/NewAppUI/Scene/Boot.unity
+2
-0
TfUI.prefab
My project/Assets/Prefabs/TF/Art/TfUI.prefab
+7
-0
TfUI.prefab
My project/Assets/Prefabs/TF/Phone Art/TfUI.prefab
+23
-20
SSApiManager.cs
...oject/Assets/ScienceStreet/Shared/Scripts/SSApiManager.cs
+2
-0
UIPause.cs
My project/Assets/ScienceStreet/Shared/Scripts/UIPause.cs
+7
-1
TfGameManager.cs
My project/Assets/ScienceStreet/TF/Scripts/TfGameManager.cs
+19
-5
TfUIManager.cs
My project/Assets/ScienceStreet/TF/Scripts/TfUIManager.cs
+24
-1
No files found.
My project/Assets/App/Infrastructure/Core/AppRouter.cs
View file @
1f5a8eb6
...
...
@@ -6,6 +6,7 @@ using Supabase.Gotrue;
using
Supabase.Gotrue.Interfaces
;
using
UnityEngine
;
using
UnityEngine.SceneManagement
;
using
TMPro
;
public
class
AppRouter
:
MonoBehaviour
{
...
...
@@ -15,9 +16,14 @@ public class AppRouter : MonoBehaviour
[
Header
(
"Splash UI (Boot Scene Only)"
)]
[
SerializeField
]
private
GameObject
splashScreen
;
[
SerializeField
]
private
GameObject
errorPanel
;
[
SerializeField
]
private
TextMeshProUGUI
statusText
;
[
Header
(
"Settings"
)]
public
TransitionSettings
transitionSettings
;
private
bool
_booted
;
[
Header
(
"Debug Testing"
)]
[
Tooltip
(
"Check this in the Inspector to simulate network loss and test the 'Waiting' loop."
)]
[
SerializeField
]
private
bool
simulateNetworkFailure
;
private
void
Awake
()
{
...
...
@@ -30,6 +36,7 @@ public class AppRouter : MonoBehaviour
_instance
=
this
;
DontDestroyOnLoad
(
gameObject
);
// Standard mobile optimizations
Application
.
targetFrameRate
=
Screen
.
currentResolution
.
refreshRate
;
Screen
.
orientation
=
ScreenOrientation
.
Portrait
;
}
...
...
@@ -42,7 +49,7 @@ public class AppRouter : MonoBehaviour
private
void
HandleBackButton
()
{
//
Don't interrupt active challenges
//
Safety: Don't let the back button break an active game session
if
(
ChallengeManager
.
Instance
!=
null
&&
ChallengeManager
.
Instance
.
IsChallengeRunning
)
return
;
...
...
@@ -66,74 +73,119 @@ public class AppRouter : MonoBehaviour
var
cached
=
UserService
.
Instance
.
LoadFromCache
();
TransitionManager
.
Instance
().
onTransitionCutPointReached
+=
HideSplash
;
bool
ready
=
await
SupabaseManager
.
Instance
.
Initialize
();
if
(!
ready
)
{
if
(
cached
!=
null
)
{
GoToHome
();
return
;
}
ShowError
(
"Failed to connect"
);
return
;
}
// --- STEP 1: Network Connection Loop ---
// Execution halts here until isConnected is true
await
EnsureNetworkConnection
();
// --- STEP 2: Authentication Session ---
UpdateStatus
(
"Checking session..."
);
var
authResult
=
await
SupabaseAuthentication
.
Instance
.
EnsureSession
();
if
(
authResult
.
IsT1
)
if
(
authResult
.
IsT1
)
// No valid session found
{
if
(
cached
!=
null
)
{
GoToHome
();
return
;
}
if
(
cached
!=
null
)
{
Debug
.
Log
(
"[Boot] Offline/No session, using cache."
);
GoToHome
();
return
;
}
GoToLogin
();
return
;
}
// --- STEP 3: Load User Profile ---
UpdateStatus
(
"Fetching profile..."
);
var
prof
=
await
UserService
.
Instance
.
GetCurrentUser
();
prof
.
Switch
(
async
success
=>
{
TransitionManager
.
Instance
().
Transition
(
"MainMenu"
,
transitionSettings
,
0f
);
UserService
.
Instance
.
StartListening
();
},
error
=>
{
if
(
cached
!=
null
)
{
Debug
.
LogWarning
(
$"[Boot] Network profile fetch failed, using cache"
);
GoToHome
();
}
else
{
Debug
.
LogError
(
$"[Boot] Failed to load user profile:
{
error
}
"
);
GoToLogin
();
}
}
);
async
success
=>
{
UpdateStatus
(
"Welcome back!"
);
TransitionManager
.
Instance
().
Transition
(
"MainMenu"
,
transitionSettings
,
0.5f
);
UserService
.
Instance
.
StartListening
();
},
error
=>
{
// If profile fetch fails but we have a cache, let them in
if
(
cached
!=
null
)
{
Debug
.
LogWarning
(
$"[Boot] Profile fetch failed, falling back to cache."
);
GoToHome
();
}
else
{
Debug
.
LogError
(
$"[Boot] Critical load error:
{
error
}
"
);
GoToLogin
();
}
}
);
}
private
async
UniTask
EnsureNetworkConnection
()
{
bool
isConnected
=
false
;
int
attempts
=
0
;
while
(!
isConnected
)
{
attempts
++;
UpdateStatus
(
attempts
==
1
?
"Connecting..."
:
"Waiting for network..."
);
if
(
simulateNetworkFailure
)
{
Debug
.
LogWarning
(
"[TEST] simulateNetworkFailure is ON. Mocking connection failure."
);
isConnected
=
false
;
}
else
{
isConnected
=
await
SupabaseManager
.
Instance
.
Initialize
();
}
if
(!
isConnected
)
{
// Wait 3 seconds before the next heartbeat
// Uses the object's token to stop if the user quits the app
await
UniTask
.
Delay
(
TimeSpan
.
FromSeconds
(
3
),
cancellationToken
:
this
.
GetCancellationTokenOnDestroy
());
}
}
UpdateStatus
(
"Connected!"
);
await
UniTask
.
Delay
(
500
);
// Visual polish
}
// ─── Auth State Listener (Safety Net Only) ───────────────────────
private
void
UpdateStatus
(
string
message
)
{
if
(
statusText
!=
null
)
statusText
.
text
=
message
;
Debug
.
Log
(
$"[AppRouter]
{
message
}
"
);
}
// ─── Auth State Listener (Safety Net) ───────────────────────────
private
void
OnAuthStateChanged
(
IGotrueClient
<
Supabase
.
Gotrue
.
User
,
Supabase
.
Gotrue
.
Session
>
sender
,
Constants
.
AuthState
newState
)
{
switch
(
newState
)
{
case
Constants
.
AuthState
.
SignedOut
:
// Only react if WE didn't trigger the sign-out
if
(!
SupabaseAuthentication
.
Instance
.
IsLoading
)
{
Debug
.
LogWarning
(
"[Auth] Unexpected sign-out detected"
);
UserService
.
Instance
.
ClearUser
();
GoToLogin
();
}
break
;
case
Constants
.
AuthState
.
TokenRefreshed
:
Debug
.
Log
(
"[Auth]
Token refreshed
"
);
Debug
.
Log
(
"[Auth]
Session token refreshed.
"
);
break
;
}
}
// ─── Navigation
───────
───────────────────────────────────────────
public
async
static
void
GoToLogin
()
// ─── Navigation
Logic
───────────────────────────────────────────
public
static
void
GoToLogin
()
{
TransitionManager
.
Instance
().
Transition
(
"Login"
,
_instance
.
transitionSettings
,
0f
);
}
public
async
static
void
GoToHome
()
public
static
void
GoToHome
()
{
TransitionManager
.
Instance
().
Transition
(
"MainMenu"
,
_instance
.
transitionSettings
,
0f
);
UserService
.
Instance
.
StartListening
();
...
...
@@ -151,7 +203,7 @@ public class AppRouter : MonoBehaviour
try
{
SSAudioManager
.
Instance
?.
StopMusic
();
}
catch
{
}
}
// ───
Helpers ───
──────────────────────────────────────────────────
// ───
UI Helpers
──────────────────────────────────────────────────
private
static
void
HideSplash
()
{
if
(
_instance
==
null
)
return
;
...
...
@@ -163,6 +215,6 @@ public class AppRouter : MonoBehaviour
{
if
(
splashScreen
!=
null
)
splashScreen
.
SetActive
(
false
);
if
(
errorPanel
!=
null
)
errorPanel
.
SetActive
(
true
);
Debug
.
LogError
(
$"[Boot]
{
message
}
"
);
Debug
.
LogError
(
$"[Boot
Error
]
{
message
}
"
);
}
}
\ No newline at end of file
My project/Assets/App/Infrastructure/Core/SupabaseManager.cs
View file @
1f5a8eb6
...
...
@@ -50,23 +50,23 @@ public class SupabaseManager
client
.
Auth
.
SetPersistence
(
new
UnitySession
());
client
.
Auth
.
Options
.
AllowUnconfirmedUserSessions
=
true
;
//
string url = $"{SupabaseSettings.SupabaseURL}/auth/v1/settings?apikey={SupabaseSettings.SupabaseAnonKey}";
string
url
=
$"
{
SupabaseSettings
.
SupabaseURL
}
/auth/v1/settings?apikey=
{
SupabaseSettings
.
SupabaseAnonKey
}
"
;
// await client.InitializeAsync();
//
try
//
{
//
client.Auth.Online = await _networkStatus.StartAsync(url);
//
}
//
catch (NotSupportedException)
//
{
//
client.Auth.Online = true;
//
}
//
catch (Exception e)
//
{
//
Debug.LogWarning($"Network check failed: {e.Message}");
//
client.Auth.Online = false;
//
}
try
{
client
.
Auth
.
Online
=
await
_networkStatus
.
StartAsync
(
url
);
}
catch
(
NotSupportedException
)
{
client
.
Auth
.
Online
=
true
;
}
catch
(
Exception
e
)
{
Debug
.
LogWarning
(
$"Network check failed:
{
e
.
Message
}
"
);
client
.
Auth
.
Online
=
false
;
}
// if (client.Auth.Online)
// {
...
...
My project/Assets/App/Infrastructure/User/UserService.cs
View file @
1f5a8eb6
...
...
@@ -6,7 +6,6 @@ using Newtonsoft.Json;
using
OneOf
;
using
Supabase.Realtime
;
using
Supabase.Realtime.PostgresChanges
;
using
Unity.VisualScripting
;
using
UnityEngine
;
public
class
UserService
...
...
My project/Assets/App/UI/HomeController.cs
View file @
1f5a8eb6
...
...
@@ -95,6 +95,7 @@ public class HomeController : MonoBehaviour
SetPlayButtonsEnabled
(
enough
);
},
_
=>
SetPlayButtonsEnabled
(
false
),
curriculumId
:
1
,
gradeId
:
user
.
Grade
,
termId
:
user
.
Term
));
...
...
My project/Assets/AppUI/NewAppUI/Scene/Boot.unity
View file @
1f5a8eb6
...
...
@@ -166,7 +166,9 @@ MonoBehaviour:
m_EditorClassIdentifier
:
Assembly-CSharp::AppRouter
splashScreen
:
{
fileID
:
90795484556287063
}
errorPanel
:
{
fileID
:
0
}
statusText
:
{
fileID
:
0
}
transitionSettings
:
{
fileID
:
11400000
,
guid
:
91673b50629b1ae4f938d0b25135d085
,
type
:
2
}
simulateNetworkFailure
:
0
---
!u!1
&787965442
GameObject
:
m_ObjectHideFlags
:
0
...
...
My project/Assets/Prefabs/TF/Art/TfUI.prefab
View file @
1f5a8eb6
...
...
@@ -1321,20 +1321,27 @@ MonoBehaviour:
_loadingUI
:
{
fileID
:
4105729685514656015
}
_errorUI
:
{
fileID
:
8668403456112399721
}
_resultsUI
:
{
fileID
:
8614017441097344094
}
_feedbackGroup
:
{
fileID
:
5181556637890600282
}
_scoreText
:
{
fileID
:
5935917613051726348
}
_streakText
:
{
fileID
:
6655817245277015576
}
_scoreLbl
:
{
fileID
:
0
}
_loadingText
:
{
fileID
:
2750036649835959240
}
_errorText
:
{
fileID
:
5202410726077148544
}
_progressLabel
:
{
fileID
:
876496144990673683
}
_resultTitle
:
{
fileID
:
7300533697225226430
}
_resultScore
:
{
fileID
:
5737192048517657640
}
_resultStats
:
{
fileID
:
1630567241621742439
}
_feedbackText
:
{
fileID
:
2735330587039562112
}
_feedbackBg
:
{
fileID
:
8779464442449399176
}
_restartButton
:
{
fileID
:
7997833608038347806
}
_returnToHomeButton
:
{
fileID
:
7997833608038347806
}
_timerSlider
:
{
fileID
:
4514849613205295364
}
_timerFill
:
{
fileID
:
4203006633935581820
}
_timerText
:
{
fileID
:
1760636326841778451
}
_maxTime
:
30
_pointsContainer
:
{
fileID
:
0
}
_activePointColor
:
{
r
:
0
,
g
:
0
,
b
:
0
,
a
:
0
}
_inactivePointColor
:
{
r
:
0
,
g
:
0
,
b
:
0
,
a
:
0
}
onRestartClicked
:
m_PersistentCalls
:
m_Calls
:
[]
...
...
My project/Assets/Prefabs/TF/Phone Art/TfUI.prefab
View file @
1f5a8eb6
...
...
@@ -33,10 +33,10 @@ RectTransform:
m_Children
:
[]
m_Father
:
{
fileID
:
5824509147393400757
}
m_LocalEulerAnglesHint
:
{
x
:
0
,
y
:
0
,
z
:
0
}
m_AnchorMin
:
{
x
:
0
,
y
:
1
}
m_AnchorMax
:
{
x
:
0
,
y
:
1
}
m_AnchoredPosition
:
{
x
:
22.572838
,
y
:
-25.96685
}
m_SizeDelta
:
{
x
:
0
,
y
:
51.9337
}
m_AnchorMin
:
{
x
:
0
,
y
:
0
}
m_AnchorMax
:
{
x
:
0
,
y
:
0
}
m_AnchoredPosition
:
{
x
:
22.572838
,
y
:
0
}
m_SizeDelta
:
{
x
:
51.9337
,
y
:
0
}
m_Pivot
:
{
x
:
0.5
,
y
:
0.5
}
---
!u!222
&9055497536415541340
CanvasRenderer
:
...
...
@@ -868,10 +868,10 @@ RectTransform:
m_Children
:
[]
m_Father
:
{
fileID
:
5824509147393400757
}
m_LocalEulerAnglesHint
:
{
x
:
0
,
y
:
0
,
z
:
0
}
m_AnchorMin
:
{
x
:
0
,
y
:
1
}
m_AnchorMax
:
{
x
:
0
,
y
:
1
}
m_AnchoredPosition
:
{
x
:
144.8642
,
y
:
-25.96685
}
m_SizeDelta
:
{
x
:
0
,
y
:
51.9337
}
m_AnchorMin
:
{
x
:
0
,
y
:
0
}
m_AnchorMax
:
{
x
:
0
,
y
:
0
}
m_AnchoredPosition
:
{
x
:
144.8642
,
y
:
0
}
m_SizeDelta
:
{
x
:
51.9337
,
y
:
0
}
m_Pivot
:
{
x
:
0.5
,
y
:
0.5
}
---
!u!222
&6316850651786239132
CanvasRenderer
:
...
...
@@ -1210,10 +1210,10 @@ RectTransform:
m_Children
:
[]
m_Father
:
{
fileID
:
5824509147393400757
}
m_LocalEulerAnglesHint
:
{
x
:
0
,
y
:
0
,
z
:
0
}
m_AnchorMin
:
{
x
:
0
,
y
:
1
}
m_AnchorMax
:
{
x
:
0
,
y
:
1
}
m_AnchoredPosition
:
{
x
:
83.71851
,
y
:
-25.96685
}
m_SizeDelta
:
{
x
:
0
,
y
:
51.9337
}
m_AnchorMin
:
{
x
:
0
,
y
:
0
}
m_AnchorMax
:
{
x
:
0
,
y
:
0
}
m_AnchoredPosition
:
{
x
:
83.71851
,
y
:
0
}
m_SizeDelta
:
{
x
:
51.9337
,
y
:
0
}
m_Pivot
:
{
x
:
0.5
,
y
:
0.5
}
---
!u!222
&6319844450247911941
CanvasRenderer
:
...
...
@@ -2195,10 +2195,10 @@ RectTransform:
m_Children
:
[]
m_Father
:
{
fileID
:
5824509147393400757
}
m_LocalEulerAnglesHint
:
{
x
:
0
,
y
:
0
,
z
:
0
}
m_AnchorMin
:
{
x
:
0
,
y
:
1
}
m_AnchorMax
:
{
x
:
0
,
y
:
1
}
m_AnchoredPosition
:
{
x
:
206.00986
,
y
:
-25.96685
}
m_SizeDelta
:
{
x
:
0
,
y
:
51.9337
}
m_AnchorMin
:
{
x
:
0
,
y
:
0
}
m_AnchorMax
:
{
x
:
0
,
y
:
0
}
m_AnchoredPosition
:
{
x
:
206.00986
,
y
:
0
}
m_SizeDelta
:
{
x
:
51.9337
,
y
:
0
}
m_Pivot
:
{
x
:
0.5
,
y
:
0.5
}
---
!u!222
&3778932895135096301
CanvasRenderer
:
...
...
@@ -2381,6 +2381,7 @@ MonoBehaviour:
_loadingUI
:
{
fileID
:
948396739458356726
}
_errorUI
:
{
fileID
:
4448024252030771562
}
_resultsUI
:
{
fileID
:
1265578760517736726
}
_feedbackGroup
:
{
fileID
:
4497114863431471683
}
_scoreText
:
{
fileID
:
7283828466168530179
}
_streakText
:
{
fileID
:
3088443959907424236
}
_scoreLbl
:
{
fileID
:
5924483057703210132
}
...
...
@@ -2390,6 +2391,8 @@ MonoBehaviour:
_resultTitle
:
{
fileID
:
3377821766872872317
}
_resultScore
:
{
fileID
:
2058651398905202117
}
_resultStats
:
{
fileID
:
2189195751882486028
}
_feedbackText
:
{
fileID
:
2715045871399486055
}
_feedbackBg
:
{
fileID
:
609508365388699558
}
_restartButton
:
{
fileID
:
2142933248170327394
}
_returnToHomeButton
:
{
fileID
:
6128910297614538796
}
_timerSlider
:
{
fileID
:
3613290988306101471
}
...
...
@@ -2829,10 +2832,10 @@ RectTransform:
m_Children
:
[]
m_Father
:
{
fileID
:
5824509147393400757
}
m_LocalEulerAnglesHint
:
{
x
:
0
,
y
:
0
,
z
:
0
}
m_AnchorMin
:
{
x
:
0
,
y
:
1
}
m_AnchorMax
:
{
x
:
0
,
y
:
1
}
m_AnchoredPosition
:
{
x
:
267.15555
,
y
:
-25.96685
}
m_SizeDelta
:
{
x
:
0
,
y
:
51.9337
}
m_AnchorMin
:
{
x
:
0
,
y
:
0
}
m_AnchorMax
:
{
x
:
0
,
y
:
0
}
m_AnchoredPosition
:
{
x
:
267.15555
,
y
:
0
}
m_SizeDelta
:
{
x
:
51.9337
,
y
:
0
}
m_Pivot
:
{
x
:
0.5
,
y
:
0.5
}
---
!u!222
&1293769170803587111
CanvasRenderer
:
...
...
My project/Assets/ScienceStreet/Shared/Scripts/SSApiManager.cs
View file @
1f5a8eb6
...
...
@@ -349,6 +349,7 @@ namespace com.al_arcade.shared
// ═══════════════════════════════════════════════════
public
IEnumerator
GetChapters
(
Action
<
ChapterInfo
[
]>
onSuccess
,
Action
<
string
>
onError
,
int
curriculumId
=
0
,
int
subjectId
=
0
,
int
gradeId
=
0
,
int
termId
=
0
)
...
...
@@ -357,6 +358,7 @@ namespace com.al_arcade.shared
if
(
subjectId
>
0
)
p
[
"subject_id"
]
=
subjectId
.
ToString
();
if
(
gradeId
>
0
)
p
[
"grade_id"
]
=
gradeId
.
ToString
();
if
(
termId
>
0
)
p
[
"term_id"
]
=
termId
.
ToString
();
if
(
curriculumId
>
0
)
p
[
"curriculum_id"
]
=
curriculumId
.
ToString
();
yield
return
GetRequest
(
"get_chapters"
,
p
,
json
=>
...
...
My project/Assets/ScienceStreet/Shared/Scripts/UIPause.cs
View file @
1f5a8eb6
...
...
@@ -24,18 +24,24 @@ public class UIPause : MonoBehaviour
if
(
quitButton
!=
null
)
quitButton
.
onClick
.
AddListener
(
QuitGame
);
pauseMenuCanvasGroup
.
gameObject
.
SetActive
(
false
);
}
private
void
PauseGame
()
{
Time
.
timeScale
=
0f
;
pauseMenuCanvasGroup
.
gameObject
.
SetActive
(
true
);
pauseMenuCanvasGroup
.
DOFade
(
1f
,
0.25f
).
From
(
0f
).
SetUpdate
(
true
);
}
private
void
ResumeGame
()
{
Time
.
timeScale
=
1f
;
pauseMenuCanvasGroup
.
DOFade
(
0f
,
0.25f
).
From
(
1f
).
SetUpdate
(
true
);
pauseMenuCanvasGroup
.
DOFade
(
0f
,
0.25f
).
From
(
1f
).
SetUpdate
(
true
).
OnComplete
(()
=>
{
pauseMenuCanvasGroup
.
gameObject
.
SetActive
(
false
);
});
}
private
void
QuitGame
()
...
...
My project/Assets/ScienceStreet/TF/Scripts/TfGameManager.cs
View file @
1f5a8eb6
...
...
@@ -200,12 +200,22 @@ namespace com.al_arcade.tf
_correctCount
++;
_streak
++;
_progress
++;
_score
+=
CalculateStreakScore
();
int
points
=
CalculateStreakScore
();
_score
+=
points
;
// timer before productionLine to avoid Race Condition
UpdateTimerBy
(
4f
);
uiManager
?.
UpdateTimer
(
_timeLeft
,
true
);
if
(
handController
!=
null
)
handController
.
PlayCorrectFeedback
(
playerSaidTrue
);
if
(
productionLine
!=
null
)
yield
return
productionLine
.
MoveForward
(
stepDistance
);
if
(
questionScreen
!=
null
)
questionScreen
.
ShowFeedback
(
true
,
_streak
);
if
(
uiManager
!=
null
)
uiManager
.
ShowFeedback
(
$"ممتاز!
{
points
}
+"
,
true
);
var
audio
=
SSAudioManager
.
Instance
;
if
(
audio
!=
null
)
{
if
(
audio
.
sfxCorrect
!=
null
)
audio
.
PlayCorrect
();
else
audio
.
PlayCorrectBeep
();
}
...
...
@@ -214,8 +224,7 @@ namespace com.al_arcade.tf
if
(
particles
!=
null
)
particles
.
PlayCorrectBurst
(
new
Vector3
(-
2
,
6f
,
13
));
UpdateTimerBy
(
4f
);
uiManager
?.
UpdateTimer
(
_timeLeft
,
true
);
}
else
{
...
...
@@ -223,10 +232,17 @@ namespace com.al_arcade.tf
_streak
=
0
;
_progress
=
Mathf
.
Max
(
0
,
_progress
-
1
);
// timer before productionLine to avoid Race Condition
UpdateTimerBy
(-
2f
);
uiManager
?.
UpdateTimer
(
_timeLeft
,
false
);
if
(
handController
!=
null
)
handController
.
PlayWrongFeedback
(
playerSaidTrue
);
if
(
productionLine
!=
null
)
yield
return
productionLine
.
MoveBackward
(
stepDistance
);
if
(
questionScreen
!=
null
)
questionScreen
.
ShowFeedback
(
false
,
0
);
if
(
uiManager
!=
null
)
uiManager
.
ShowFeedback
(
"حاول مرة أخرى"
,
false
);
var
audio
=
SSAudioManager
.
Instance
;
if
(
audio
!=
null
)
{
if
(
audio
.
sfxWrong
!=
null
)
audio
.
PlayWrong
();
else
audio
.
PlayWrongBeep
();
}
...
...
@@ -238,8 +254,6 @@ namespace com.al_arcade.tf
.
SetEase
(
Ease
.
OutQuad
).
SetId
(
"camShake"
);
}
UpdateTimerBy
(-
2f
);
uiManager
?.
UpdateTimer
(
_timeLeft
,
false
);
}
onAnswerGiven
?.
Invoke
(
isCorrect
);
...
...
My project/Assets/ScienceStreet/TF/Scripts/TfUIManager.cs
View file @
1f5a8eb6
...
...
@@ -14,11 +14,13 @@ namespace com.al_arcade.tf
public
class
TfUIManager
:
MonoBehaviour
{
[
SerializeField
]
private
Canvas
_canvas
;
[
SerializeField
]
private
CanvasGroup
_gameUI
,
_loadingUI
,
_errorUI
,
_resultsUI
;
[
SerializeField
]
private
CanvasGroup
_gameUI
,
_loadingUI
,
_errorUI
,
_resultsUI
,
_feedbackGroup
;
[
SerializeField
]
private
UniText
_scoreText
,
_streakText
,
_scoreLbl
;
[
SerializeField
]
private
ArabicTextMeshProUGUI
_loadingText
,
_errorText
;
[
SerializeField
]
private
UniText
_progressLabel
;
[
SerializeField
]
private
UniText
_resultTitle
,
_resultScore
,
_resultStats
;
[
SerializeField
]
private
UniText
_feedbackText
;
[
SerializeField
]
private
Image
_feedbackBg
;
[
SerializeField
]
private
Button
_restartButton
;
[
SerializeField
]
protected
Button
_returnToHomeButton
;
...
...
@@ -180,6 +182,27 @@ namespace com.al_arcade.tf
if
(
_progressLabel
!=
null
)
_progressLabel
.
Text
=
$"
{
cur
}
/
{
total
}
"
;
}
public
void
ShowFeedback
(
string
message
,
bool
isCorrect
)
{
if
(
_feedbackText
!=
null
)
_feedbackText
.
Text
=
message
;
if
(
_feedbackBg
!=
null
)
_feedbackBg
.
color
=
SSColorPalette
.
WithAlpha
(
isCorrect
?
SSColorPalette
.
Success
:
SSColorPalette
.
Danger
,
0.92f
);
DOTween
.
Kill
(
_feedbackGroup
,
"fbAnim"
);
_feedbackGroup
.
alpha
=
0
;
var
bgRect
=
_feedbackBg
?.
rectTransform
;
if
(
bgRect
!=
null
)
{
bgRect
.
localScale
=
new
Vector3
(
0.3f
,
0f
,
1f
);
var
seq
=
DOTween
.
Sequence
().
SetId
(
"fbAnim"
);
seq
.
Append
(
_feedbackGroup
.
DOFade
(
1f
,
0.12f
));
seq
.
Join
(
bgRect
.
DOScaleX
(
1f
,
0.25f
).
SetEase
(
Ease
.
OutBack
));
seq
.
Join
(
bgRect
.
DOScaleY
(
1f
,
0.2f
).
SetEase
(
Ease
.
OutBack
).
SetDelay
(
0.04f
));
seq
.
AppendInterval
(
1f
);
seq
.
Append
(
_feedbackGroup
.
DOFade
(
0f
,
0.3f
));
}
}
// ─── Loading / Error ──────────────────────────────────────────────────
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment