QuizUIManager.cs 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. using TMPro;
  4. using System.Collections;
  5. public class QuizUIManager : MonoBehaviour
  6. {
  7. // 题库管理器
  8. public QuestionManager questionManager;
  9. // 题目文本
  10. public TextMeshProUGUI questionText;
  11. // 选项A按钮
  12. public Button optionAButton;
  13. // 选项B按钮
  14. public Button optionBButton;
  15. // 选项A文本
  16. public TextMeshProUGUI optionAText;
  17. // 选项B文本
  18. public TextMeshProUGUI optionBText;
  19. // 答题反馈文本
  20. public TextMeshProUGUI feedbackText;
  21. // 进度条
  22. public Slider progressBar;
  23. // 答案窗口
  24. public GameObject answerWindow; // 添加对 Answer Window 的引用
  25. // 开始战斗按钮
  26. public Button startBattleButton; // 添加对 Start Battle 按钮的引用
  27. // 是否允许答题
  28. private bool canAnswer = true;
  29. // 答案窗口CanvasGroup(用于淡入淡出)
  30. private CanvasGroup answerWindowCanvasGroup;
  31. // 淡入淡出持续时间
  32. private float fadeDuration = 1.5f; // 淡入淡出持续时间
  33. /// <summary>
  34. /// 初始化答案窗口CanvasGroup
  35. /// </summary>
  36. void Awake()
  37. {
  38. Debug.Log("QuizUIManager Awake");
  39. if (answerWindow != null)
  40. {
  41. answerWindowCanvasGroup = answerWindow.GetComponent<CanvasGroup>();
  42. if (answerWindowCanvasGroup == null)
  43. {
  44. answerWindowCanvasGroup = answerWindow.AddComponent<CanvasGroup>();
  45. }
  46. // 初始设置为完全透明且不可交互
  47. answerWindowCanvasGroup.alpha = 0f;
  48. answerWindowCanvasGroup.interactable = false;
  49. answerWindowCanvasGroup.blocksRaycasts = false;
  50. }
  51. }
  52. /// <summary>
  53. /// 启动时检查组件并注册按钮事件
  54. /// </summary>
  55. void Start()
  56. {
  57. Debug.Log("QuizUIManager Start");
  58. // 检查所有必要组件
  59. if (questionManager == null)
  60. {
  61. Debug.LogError("QuestionManager 未设置!请在 Inspector 中设置 QuestionManager 引用");
  62. return;
  63. }
  64. if (questionText == null)
  65. {
  66. Debug.LogError("questionText 未设置!请在 Inspector 中设置 Question Text 引用");
  67. return;
  68. }
  69. if (optionAButton == null || optionBButton == null)
  70. {
  71. Debug.LogError("选项按钮未设置!请在 Inspector 中设置 Option A/B Button 引用");
  72. return;
  73. }
  74. if (optionAText == null || optionBText == null)
  75. {
  76. Debug.LogError("选项文本未设置!请在 Inspector 中设置 Option A/B Text 引用");
  77. return;
  78. }
  79. // 添加按钮监听
  80. optionAButton.onClick.AddListener(() => OnAnswerSelected(true));
  81. optionBButton.onClick.AddListener(() => OnAnswerSelected(false));
  82. // 显示第一道题
  83. // Invoke("DisplayCurrentQuestion", 0.1f);
  84. // 稍微延迟一下,确保 QuestionManager 已经初始化
  85. if (startBattleButton != null)
  86. {
  87. startBattleButton.onClick.AddListener(OnStartBattleClicked);
  88. }
  89. }
  90. /// <summary>
  91. /// 开始战斗按钮点击,延迟显示答题窗口
  92. /// </summary>
  93. void OnStartBattleClicked()
  94. {
  95. // 禁用开始战斗按钮,防止重复点击
  96. if (startBattleButton != null)
  97. {
  98. startBattleButton.interactable = false;
  99. }
  100. // 3秒后显示答题窗口
  101. Invoke("ShowAnswerWindow", 3f);
  102. }
  103. /// <summary>
  104. /// 显示答题窗口并淡入
  105. /// </summary>
  106. void ShowAnswerWindow()
  107. {
  108. if (answerWindow != null)
  109. {
  110. answerWindow.SetActive(true);
  111. //DisplayCurrentQuestion();
  112. StartCoroutine(FadeIn()); // 使用协程来实现淡入效果
  113. }
  114. }
  115. /// <summary>
  116. /// 答案窗口淡入协程
  117. /// </summary>
  118. IEnumerator FadeIn()
  119. {
  120. float elapsedTime = 0f;
  121. // 确保窗口可见但完全透明
  122. answerWindowCanvasGroup.alpha = 0f;
  123. answerWindowCanvasGroup.interactable = true;
  124. answerWindowCanvasGroup.blocksRaycasts = true;
  125. // 逐渐增加透明度
  126. while (elapsedTime < fadeDuration)
  127. {
  128. elapsedTime += Time.deltaTime;
  129. float newAlpha = Mathf.Lerp(0f, 1f, elapsedTime / fadeDuration);
  130. answerWindowCanvasGroup.alpha = newAlpha;
  131. yield return null;
  132. }
  133. // 确保完全显示
  134. answerWindowCanvasGroup.alpha = 1f;
  135. // 显示第一道题
  136. DisplayCurrentQuestion();
  137. }
  138. /// <summary>
  139. /// 隐藏答题窗口并淡出
  140. /// </summary>
  141. public void HideAnswerWindow()
  142. {
  143. if (answerWindow != null)
  144. {
  145. StartCoroutine(FadeOut());
  146. }
  147. }
  148. /// <summary>
  149. /// 答案窗口淡出协程
  150. /// </summary>
  151. IEnumerator FadeOut()
  152. {
  153. float elapsedTime = 0f;
  154. // 逐渐减少透明度
  155. while (elapsedTime < fadeDuration)
  156. {
  157. elapsedTime += Time.deltaTime;
  158. float newAlpha = Mathf.Lerp(1f, 0f, elapsedTime / fadeDuration);
  159. answerWindowCanvasGroup.alpha = newAlpha;
  160. yield return null;
  161. }
  162. // 完全隐藏窗口
  163. answerWindowCanvasGroup.alpha = 0f;
  164. answerWindowCanvasGroup.interactable = false;
  165. answerWindowCanvasGroup.blocksRaycasts = false;
  166. answerWindow.SetActive(false);
  167. }
  168. /// <summary>
  169. /// 显示当前题目和选项,刷新UI
  170. /// </summary>
  171. void DisplayCurrentQuestion()
  172. {
  173. Debug.Log("显示新题目");
  174. if (questionManager == null)
  175. {
  176. Debug.LogError("QuestionManager 为空!");
  177. return;
  178. }
  179. QuestionData currentQuestion = questionManager.GetCurrentQuestion();
  180. if (currentQuestion != null)
  181. {
  182. Debug.Log($"当前题目:{currentQuestion.multiplier1} × {currentQuestion.multiplier2}");
  183. // 显示题目
  184. if (questionText != null)
  185. {
  186. questionText.text = $"{currentQuestion.multiplier1} × {currentQuestion.multiplier2} = ?";
  187. }
  188. else
  189. {
  190. Debug.LogError("questionText 为空!");
  191. }
  192. // 根据 isAnswerA 决定正确答案的位置
  193. if (currentQuestion.isAnswerA)
  194. {
  195. if (optionAText != null && optionBText != null)
  196. {
  197. optionAText.text = currentQuestion.result.ToString();
  198. optionBText.text = currentQuestion.wrongAnswer.ToString();
  199. }
  200. }
  201. else
  202. {
  203. if (optionAText != null && optionBText != null)
  204. {
  205. optionAText.text = currentQuestion.wrongAnswer.ToString();
  206. optionBText.text = currentQuestion.result.ToString();
  207. }
  208. }
  209. // 重置UI状态
  210. if (feedbackText != null)
  211. {
  212. feedbackText.text = "";
  213. }
  214. canAnswer = true;
  215. if (optionAButton != null && optionBButton != null)
  216. {
  217. optionAButton.interactable = true;
  218. optionBButton.interactable = true;
  219. }
  220. if (progressBar != null)
  221. {
  222. progressBar.value = questionManager.GetProgress();
  223. }
  224. }
  225. else
  226. {
  227. Debug.LogError("获取当前题目失败!currentQuestion 为空");
  228. }
  229. }
  230. /// <summary>
  231. /// 选项按钮点击,判断答案并反馈
  232. /// </summary>
  233. /// <param name="selectedA">是否选择A</param>
  234. void OnAnswerSelected(bool selectedA)
  235. {
  236. if (!canAnswer) return;
  237. canAnswer = false;
  238. bool isCorrect = questionManager.CheckAnswer(selectedA);
  239. // 禁用按钮防止重复点击
  240. optionAButton.interactable = false;
  241. optionBButton.interactable = false;
  242. // 显示答题结果
  243. feedbackText.text = isCorrect ? "回答正确!" : "回答错误!";
  244. // 设置按钮颜色反馈
  245. SetButtonColor(optionAButton, selectedA ? isCorrect : false);
  246. SetButtonColor(optionBButton, !selectedA ? isCorrect : false);
  247. // 延迟进入下一题
  248. Invoke("ProceedToNextQuestion", 0.5f);
  249. }
  250. /// <summary>
  251. /// 设置按钮颜色反馈
  252. /// </summary>
  253. /// <param name="button">按钮</param>
  254. /// <param name="isCorrect">是否正确</param>
  255. void SetButtonColor(Button button, bool isCorrect)
  256. {
  257. ColorBlock colors = button.colors;
  258. colors.normalColor = isCorrect ? Color.green : Color.red;
  259. colors.selectedColor = colors.normalColor;
  260. button.colors = colors;
  261. }
  262. /// <summary>
  263. /// 进入下一题,重置按钮颜色并刷新题目
  264. /// </summary>
  265. void ProceedToNextQuestion()
  266. {
  267. // 重置按钮颜色
  268. ResetButtonColors();
  269. questionManager.NextQuestion();
  270. DisplayCurrentQuestion();
  271. }
  272. /// <summary>
  273. /// 重置按钮颜色为默认
  274. /// </summary>
  275. void ResetButtonColors()
  276. {
  277. ColorBlock defaultColors = new ColorBlock
  278. {
  279. normalColor = Color.white,
  280. highlightedColor = new Color(0.9f, 0.9f, 0.9f),
  281. pressedColor = new Color(0.8f, 0.8f, 0.8f),
  282. selectedColor = Color.white,
  283. disabledColor = new Color(0.8f, 0.8f, 0.8f, 0.5f),
  284. colorMultiplier = 1f,
  285. fadeDuration = 0.1f
  286. };
  287. optionAButton.colors = defaultColors;
  288. optionBButton.colors = defaultColors;
  289. }
  290. void OnDisable()
  291. {
  292. CancelInvoke(); // 取消所有Invoke,防止场景重载后自动触发ShowAnswerWindow等
  293. }
  294. }