Unity Punnett方格游戏答题逻辑与状态重置问题求助
Unity Punnett方格游戏答题逻辑与状态重置问题求助
嘿,别担心!作为Unity新手遇到这种逻辑问题太正常了,我来帮你梳理和修复代码里的问题~
先说说你当前代码的核心问题:你在Update里同时检查所有四个槽的答案匹配,这就导致哪怕你在Slot1输入了Slot2的答案,代码也会误触发isCorrect2并跳转到Slot3。我们需要改成只检查当前正在作答的槽对应的正确答案,严格按顺序推进流程。
接下来分步骤解决你的三个需求:
一、修复严格按顺序答题的逻辑
我们可以用一个整数变量currentSlotIndex来跟踪当前要答的槽序号(1对应Slot1,2对应Slot2以此类推),这样就能精准控制答题流程:
- 初始时
currentSlotIndex设为1,默认作答Slot1 - 只有当前槽的答案匹配对应正确值时,才推进到下一个槽
- 把按钮监听从
Update移到Start里(原代码重复添加监听会导致点击一次触发多次逻辑,是性能隐患)
二、单独跟踪当前槽的正确性
现在我们可以确保只有当前槽的答案会被校验,其他槽的isCorrectX不会被误触发。比如当currentSlotIndex=1时,只判断输入是否等于firstAnswer,只有匹配成功才把isCorrect1设为true,然后切换到Slot2。
三、添加状态重置功能
写一个ResetPunnettSquare()方法,用来一键重置所有状态:
- 把所有
isCorrectX和allCorrect设为false - 清空四个槽的文本内容
- 把
currentSlotIndex改回1,重新设置slotToAnswer为Slot1
修改后的完整代码
using TMPro; using UnityEngine; using UnityEngine.UI; public class AnswerScript : MonoBehaviour { public bool isCorrect1, isCorrect2, isCorrect3, isCorrect4, allCorrect; public QuizManager quizManager; public GameObject slotToAnswer; public string firstAnswer, secondAnswer, thirdAnswer, fourthAnswer, currentInput; public TextMeshProUGUI dominantText, heteroText, recessiveText; public Button dominantButton, heteroButton, recessiveButton; // 跟踪当前要作答的槽序号(1-4) private int currentSlotIndex; void Start() { // 初始化按钮(建议直接在Inspector拖引用,比Find更高效) dominantButton = GameObject.Find("Dominant").GetComponent<Button>(); heteroButton = GameObject.Find("Heterozygous").GetComponent<Button>(); recessiveButton = GameObject.Find("Recessive").GetComponent<Button>(); // 初始化文本 dominantText = dominantButton.GetComponentInChildren<TextMeshProUGUI>(); heteroText = heteroButton.GetComponentInChildren<TextMeshProUGUI>(); recessiveText = recessiveButton.GetComponentInChildren<TextMeshProUGUI>(); // 按钮监听只在Start里添加一次,避免重复绑定 dominantButton.onClick.AddListener(TexttoDominant); heteroButton.onClick.AddListener(TexttoHetero); recessiveButton.onClick.AddListener(TexttoRecessive); // 初始化答题状态 ResetPunnettSquare(); } void Update() { // 先计算所有正确答案,统一处理aA转Aa的情况 CalculateCorrectAnswers(); // 只获取当前槽的输入文本 currentInput = slotToAnswer.GetComponentInChildren<TextMeshProUGUI>().text; // 根据当前槽序号,只校验对应答案 switch(currentSlotIndex) { case 1: CheckSlot1Answer(); break; case 2: CheckSlot2Answer(); break; case 3: CheckSlot3Answer(); break; case 4: CheckSlot4Answer(); break; } } // 计算所有正确答案,统一处理aA转Aa的情况 private void CalculateCorrectAnswers() { firstAnswer = quizManager.allele1.text + quizManager.allele3.text; firstAnswer = NormalizeAlleleText(firstAnswer); secondAnswer = quizManager.allele2.text + quizManager.allele3.text; secondAnswer = NormalizeAlleleText(secondAnswer); thirdAnswer = quizManager.allele1.text + quizManager.allele4.text; thirdAnswer = NormalizeAlleleText(thirdAnswer); fourthAnswer = quizManager.allele2.text + quizManager.allele4.text; fourthAnswer = NormalizeAlleleText(fourthAnswer); } // 统一标准化等位基因文本(aA转Aa) private string NormalizeAlleleText(string text) { return text == "aA" ? "Aa" : text; } // 校验Slot1的答案 private void CheckSlot1Answer() { if(currentInput == firstAnswer && !isCorrect1) { isCorrect1 = true; currentSlotIndex = 2; slotToAnswer = GameObject.Find("Slot2"); Debug.Log("Slot1正确,现在作答Slot2"); } } // 校验Slot2的答案 private void CheckSlot2Answer() { if(currentInput == secondAnswer && !isCorrect2) { isCorrect2 = true; currentSlotIndex = 3; slotToAnswer = GameObject.Find("Slot3"); Debug.Log("Slot2正确,现在作答Slot3"); } } // 校验Slot3的答案 private void CheckSlot3Answer() { if(currentInput == thirdAnswer && !isCorrect3) { isCorrect3 = true; currentSlotIndex = 4; slotToAnswer = GameObject.Find("Slot4"); Debug.Log("Slot3正确,现在作答Slot4"); } } // 校验Slot4的答案 private void CheckSlot4Answer() { if(currentInput == fourthAnswer && !isCorrect4) { isCorrect4 = true; allCorrect = true; Debug.Log("恭喜!所有槽都答对了!"); // 这里可以加延迟重置,或者等玩家点击重置按钮 // Invoke("ResetPunnettSquare", 2f); } } // 按钮点击方法:设置当前槽为显性文本 public void TexttoDominant() { slotToAnswer.GetComponentInChildren<TextMeshProUGUI>().text = dominantText.text; } // 按钮点击方法:设置当前槽为杂合文本 public void TexttoHetero() { slotToAnswer.GetComponentInChildren<TextMeshProUGUI>().text = heteroText.text; } // 按钮点击方法:设置当前槽为隐性文本 public void TexttoRecessive() { slotToAnswer.GetComponentInChildren<TextMeshProUGUI>().text = recessiveText.text; } // 重置整个Punnett方格的状态 public void ResetPunnettSquare() { // 重置正确状态布尔值 isCorrect1 = false; isCorrect2 = false; isCorrect3 = false; isCorrect4 = false; allCorrect = false; // 重置当前槽序号和目标槽 currentSlotIndex = 1; slotToAnswer = GameObject.Find("Slot1"); // 清空所有槽的文本 GameObject.Find("Slot1").GetComponentInChildren<TextMeshProUGUI>().text = ""; GameObject.Find("Slot2").GetComponentInChildren<TextMeshProUGUI>().text = ""; GameObject.Find("Slot3").GetComponentInChildren<TextMeshProUGUI>().text = ""; GameObject.Find("Slot4").GetComponentInChildren<TextMeshProUGUI>().text = ""; Debug.Log("已重置Punnett方格,回到Slot1"); } }
关键修改点说明
- 添加
currentSlotIndex变量:精准控制当前答题阶段,彻底避免跨槽误判 - 按钮监听只绑定一次:解决原代码重复绑定导致的多次触发问题
- 拆分校验逻辑:每个槽的校验独立,逻辑更清晰,也方便后续扩展
- 提取标准化方法:把aA转Aa的逻辑抽出来,减少重复代码
- 新增重置方法:一键回到初始状态,满足你的重置需求
使用小提示
- 可以在UI里加一个重置按钮,把
ResetPunnettSquare()方法绑定到按钮的OnClick事件上 - 建议把四个Slot的引用直接拖到脚本的Inspector面板里,替换掉
GameObject.Find(),这样更高效也更稳定 - 当
allCorrect为true时,你可以触发胜利动画、切换题目等自定义逻辑
备注:内容来源于stack exchange,提问作者f0rCE
相关产品推荐
相关产品推荐

