Unity日语假名答题游戏题库优化方案咨询
Unity日语假名答题游戏优化方案需求
我是新手开发者,正在开发一款日语平假名、片假名答题游戏,玩法为展示日文假名,玩家从4个发音选项中选择正确答案。目前所有题目与答案都在Inspector中配置,两类题库各71题,每题含71个选项(超1万条字符串),新增字符时卡顿严重,尝试拆分题目与答案但不知如何操作,现寻求优化方案。参考过Brackey的答题教程、YouTube教程及ChatGPT,核心代码如下:
核心代码
GameManager类
public class GameManager : MonoBehaviour { public Animator playerAnimator; public Animator enemyAnimator; public GameObject healthBar; public GameObject enemyHealthBar; public Question[] katakanaQuestions; public Question[] hiraganaQuestions; [SerializeField] private float timeBetweenQuestions; private static List<Question> unansweredQuestions; private Question currentQuestion; [SerializeField] private TMP_Text factText; [SerializeField] private Button[] answerButtons; private int correctAnswerIndex; private bool isAnsweringQuestion = false; void Start() { LoadSelectedCategory(); SetCurrentQuestion(); } private void LoadSelectedCategory() { bool isHiraganaSelected = PlayerPrefs.GetInt("IsHiraganaSelected", 1) == 1; Question[] selectedQuestions = isHiraganaSelected ? hiraganaQuestions : katakanaQuestions; unansweredQuestions = selectedQuestions.ToList(); } void SetCurrentQuestion() { int randomQuestionIndex = Random.Range(0, unansweredQuestions.Count); currentQuestion = unansweredQuestions[randomQuestionIndex]; factText.text = currentQuestion.question; List<string> answerChoices = new List<string>(); // 创建包含正确答案和三个随机错误答案的选项列表 answerChoices.Add(currentQuestion.answers[currentQuestion.correctAnswerIndex]); // 添加正确答案 List<string> incorrectAnswers = currentQuestion.answers.ToList(); incorrectAnswers.RemoveAt(currentQuestion.correctAnswerIndex); // 移除正确答案 for (int i = 0; i < 3; i++) // 添加剩余三个随机错误答案 { int randomIndex = Random.Range(0, incorrectAnswers.Count); answerChoices.Add(incorrectAnswers[randomIndex]); incorrectAnswers.RemoveAt(randomIndex); } // 打乱顺序 int n = answerChoices.Count; while (n > 1) { n--; int k = Random.Range(0, n + 1); string temp = answerChoices[k]; answerChoices[k] = answerChoices[n]; answerChoices[n] = temp; } // 设置按钮文本 for (int i = 0; i < answerButtons.Length; i++) { answerButtons[i].GetComponentInChildren<TMP_Text>().text = answerChoices[i]; } // 正确按钮索引 correctAnswerIndex = answerChoices.IndexOf(currentQuestion.answers[currentQuestion.correctAnswerIndex]); } public void CheckAnswer(int answerIndex) { if (isAnsweringQuestion) { Debug.Log("Wait for the next question!"); return; } isAnsweringQuestion = true; // 玩家正在答题 StartCoroutine(CheckAnswerCoroutine(answerIndex)); } private IEnumerator CheckAnswerCoroutine(int answerIndex) { //yield return new WaitForSeconds(0.3f); // 存储按钮原始颜色 Color[] originalColors = new Color[answerButtons.Length]; for (int i = 0; i < answerButtons.Length; i++) { originalColors[i] = answerButtons[i].GetComponent<Image>().color; } for (int i = 0; i < answerButtons.Length; i++) { if (i == correctAnswerIndex) { // 将正确答案按钮改为特定绿色(0.1f, 0.8f, 0.1f) answerButtons[i].GetComponent<Image>().color = new Color(0.1f, 0.8f, 0.1f); } else if (i == answerIndex) { // 将选中的错误答案按钮改为特定红色(0.8f, 0.1f, 0.1f) answerButtons[i].GetComponent<Image>().color = new Color(0.8f, 0.1f, 0.1f); } } yield return new WaitForSeconds(1f); // 等待一段时间展示按钮颜色 // 重置按钮颜色为原始状态 for (int i = 0; i < answerButtons.Length; i++) { answerButtons[i].GetComponent<Image>().color = originalColors[i]; } if (answerIndex == correctAnswerIndex) { Debug.Log("Correct!"); Attack(); enemyHealthBar.GetComponent<EnemyHealthBar>().TakeDamage(1); } else { Debug.Log("Wrong answer"); GetHit(); healthBar.GetComponent<HealthBar>().TakeDamage(1); } yield return new WaitForSeconds(timeBetweenQuestions); // 等待下一题 isAnsweringQuestion = false; SetCurrentQuestion(); } }
序列化数据类
[System.Serializable] public class Question { public string question; public int correctAnswerIndex; public string[] answers; } [System.Serializable] public class KatakanaQuestion { public string question; public string[] answers; public int correctAnswerIndex; }
优化方案
1. 拆分题库与全局答案池
当前每题重复存储71个选项,数据冗余严重。改为:
- 单独维护两类假名的全局答案池:比如
hiraganaPronunciations和katakanaPronunciations,各存储71条发音字符串,仅保存一次。 - 修改
Question类,只保留核心数据,删除重复的answers数组:[System.Serializable] public class Question { public string kana; // 要展示的平假名/片假名 public string correctPronunciation; // 对应的正确发音 } - 生成选项时,从全局答案池中随机选取3个错误选项+正确答案,避免重复存储大量字符串。
2. 用ScriptableObject管理题库
将题库从Inspector直接配置改为外部文件存储,减少Editor卡顿:
- 创建
KanaQuestionSetScriptableObject,整合题库和答案池:[CreateAssetMenu(fileName = "KanaQuestionSet", menuName = "Game/Kana Question Set")] public class KanaQuestionSet : ScriptableObject { public List<Question> questions; public List<string> allPronunciations; // 该类假名的所有发音选项 } - 在Project窗口创建两个实例:
HiraganaSet和KatakanaSet,分别配置对应的题库和答案池。 - GameManager中引用这两个ScriptableObject,而非直接的数组。ScriptableObject的数据存储在外部文件,不会在Inspector中实时渲染大量字符串,大幅降低卡顿。
3. 优化选项生成逻辑
当前每次生成选项时都要复制整个答案数组,改为更高效的写法:
void SetCurrentQuestion() { // 随机选择当前题目 int randomQuestionIndex = Random.Range(0, unansweredQuestions.Count); currentQuestion = unansweredQuestions[randomQuestionIndex]; factText.text = currentQuestion.kana; // 获取当前类别的全局答案池 List<string> allPronunciations = isHiraganaSelected ? hiraganaSet.allPronunciations : katakanaSet.allPronunciations; string correctAnswer = currentQuestion.correctPronunciation; // 筛选错误选项并随机选3个 List<string> incorrectOptions = allPronunciations.Where(p => p != correctAnswer).ToList(); List<string> randomIncorrect = incorrectOptions.OrderBy(_ => Random.value).Take(3).ToList(); // 组合选项并打乱顺序 List<string> answerChoices = new List<string> { correctAnswer }; answerChoices.AddRange(randomIncorrect); answerChoices = answerChoices.OrderBy(_ => Random.value).ToList(); // 设置按钮文本 for (int i = 0; i < answerButtons.Length; i++) { answerButtons[i].GetComponentInChildren<TMP_Text>().text = answerChoices[i]; } // 记录正确答案索引 correctAnswerIndex = answerChoices.IndexOf(correctAnswer); }
4. 减少Inspector实时渲染压力
如果坚持用Inspector配置数组,可将Question数组标记为HideInInspector,通过编辑器扩展工具批量导入数据,或者在Edit Mode下禁用不必要的数据刷新逻辑。
5. 数据预加载与缓存
在Start方法中预加载选中类别的题库和答案池,避免运行时重复读取;将全局答案池缓存为HashSet或数组,提升错误选项的筛选效率。
内容的提问来源于stack exchange,提问作者Nichao
相关产品推荐
相关产品推荐

