unity制作盲盒九宫格答题

一:功能简述

点击主界面进入盲盒界面,然后选择不同的盲盒进入不同的题库,就算点击同一个盲盒也是进入不同的题库,简言之就是,每次点击盲盒,对应的题库都是随机的,

答题的时候,点击提交按钮,答对会显示正确,然后三秒后进入下一题,答错会显示正确答案,然后3秒后进入失败界面。题目支持多选,单选,判断,题库可以外部修改,同一套题的题目也是随机出现的

题目全部答对显示成功界面,但凡有一个题答错,进入失败界面,无论进入成功还是失败界面,等待一会进入主界面,再次点击进入盲盒界面,在进入下一次答题。

二:重要知识点

1、获取n个不重复的随机数

利用哈希函数获取n个不重复的随机数,思路是利用哈希函数生成随机数,然后新建一个列表存储这些数,再根据需求使用这些数字

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 生成不重复的随机数
/// </summary>
public class SetRandomNum : MonoBehaviour
{
    private List<int> randomNum = new List<int>();  //存放随机数
    // Start is called before the first frame update
    void Awake()
    {
        GetRandomNum();
    }

    // Update is called once per frame
    void Update()
    {

    }

    #region 随机顺序出题
    public void GetRandomNum()
    {
        //利用哈希函数获取随机数
        HashSet<int> nums = new HashSet<int>();
        System.Random r = new System.Random();
        //因为有9个盲盒,所以是0-8中生成随机数
        while (nums.Count != 9)
        {
            nums.Add(r.Next(0, 9));
        }
        //将生成的随机数放进列表
        foreach (var item in nums)
        {
            randomNum.Add(item);
        }
        //给子物体命名,根据子物体的名称获取题库路径
        for (int i = 0; i < transform.childCount; i++)
        {
            transform.GetChild(i).name = randomNum[i].ToString();
        }
    }

    #endregion
}

在代码中,while循环中的数量,可以根据自己的需求修改数量,如果需要修改成外部可修改的数字的话,新定义一个变量,然后用ConfigFile实现外部修改

configFile代码如下

using System.Xml.Linq;
using UnityEngine;
using System;

/// <summary>
/// xml文件读取工具
/// </summary>
public class ConfigFile
{
    static string path = Application.dataPath + "/StreamingAssets/ConfigFile.xml";

    public static DateTime LoadDeadline()
    {
        XDocument document = XDocument.Load(path);
        //获取到XML的根元素进行操作
        XElement root = document.Root;
        XElement ele = root.Element("WarningDeadline");
        DateTime deadline = Convert.ToDateTime(ele.Value);  //string格式有要求,必须是yyyy - MM - dd hh: mm: ss
        return deadline;
    }

    //获取数据
    public static string LoadString(string str)
    {
        XDocument document = XDocument.Load(path);
        //获取到XML的根元素进行操作
        XElement root = document.Root;
        XElement ele = root.Element(str);
        return ele.Value;
    }

    //更新数据
    public static void UpdateDate(string name, string value)
    {
        XDocument document = XDocument.Load(path);
        //获取到XML的根元素进行操作
        XElement root = document.Root;
        root.SetElementValue(name, value);
        document.Save(path);
    }
}

2、单选和多选的判断

这个判断单选多选正确与否的逻辑有点混乱,冗余,

整体逻辑是,先根据IsSingleChoice判断题型,然后根据题型再实现判断,

单选题是选择一个就可以完成判断,

多选题的话,是全部选对才显示正确,错选或漏选都显示错误,

同时,选择选项之前,提交按钮不能使用,提交之后,提交按钮也不能使用,只有一次选择的机会

在Update中判断

    string temp;
    string optionA = "";    //存储多选A选项
    string optionB = "";    //存储多选B选项
    string optionC = "";    //存储多选C选项
    string optionD = "";    //存储多选D选项
    bool isSub;     //是否点击了提交按钮
    private void Update()
    {
        //提交按钮是否能使用
        foreach (var item in options)
        {
            //题型图片的设置
            if (mQuestionData.answerData.Count == 4)
            {
                if (mQuestionData.IsSingleChoice)//单选图片
                {
                    QTImg.sprite = QTSprites[0];
                    QTEngImg.sprite = QTSprites[3];
                }
                else                            //多选图片
                {
                    QTImg.sprite = QTSprites[1];
                    QTEngImg.sprite = QTSprites[4];
                }
            }
            else if (mQuestionData.answerData.Count == 2)//判断图片
            {
                QTImg.sprite = QTSprites[2];
                QTEngImg.sprite = QTSprites[5];
            }

            //提取选项
            optionContent = item.optionText.GetComponent<Text>().text.Split('.');

            //题目判断
            if (item.thisToggle.isOn)
            {
                if (!isSub)
                {
                    submitBtn.interactable = true;
                    isSub = true;
                }
                //如果是单选的话,直接把正确答案跟选择的答案比较
                if (mQuestionData.IsSingleChoice)
                {
                    temp = optionContent[0];
                    //Debug.Log("单选" + optionContent[0]);
                    //temp = optionContent[0];
                }
                else
                {
                    if (optionContent[0] == "A")
                        optionA = "A";
                    else if (optionContent[0] == "B")
                        optionB = "B";
                    else if (optionContent[0] == "C")
                        optionC = "C";
                    else if (optionContent[0] == "D")
                        optionD = "D";
                    temp = optionA + optionB + optionC + optionD;
                    //Debug.Log("多选1" + temp);

                }
            }
            else
            {
                if (!mQuestionData.IsSingleChoice)
                {
                    if (optionContent[0] == "A")
                        optionA = "";
                    else if (optionContent[0] == "B")
                        optionB = "";
                    else if (optionContent[0] == "C")
                        optionC = "";
                    else if (optionContent[0] == "D")
                        optionD = "";
                    temp = optionA + optionB + optionC + optionD;
                    //Debug.Log("多选2" + temp);
                }
            }

        }

提交按钮事件,将存储的字符串跟正确答案的字符串比较,相同则表示正确,不相同就是错误

 bool isCorrent;     //是否全部答对
    string rightAnswer;
    int score = 0;
    // 题目提交事件
    private void submitClick()
    {
        isSub = true;
        //遍历当前题目的选项,有选择的就可以提交核验答案,并显示解析内容
        foreach (var item in options)
        {
            if (item.thisToggle.isOn)
            {
                rightAnswer = "";
                for (int i = 0; i < mQuestionData.answerData.Count; i++)
                {
                    switch (i)
                    {
                        case 0:
                            if (mQuestionData.answerData[i].Score > 0)//xml文档里面score属性对应的数值是用来判断该选项是否为正确选项
                            {
                                rightAnswer += "A";
                            }
                            break;
                        case 1:
                            if (mQuestionData.answerData[i].Score > 0)
                            {
                                rightAnswer += "B";
                            }
                            break;
                        case 2:
                            if (mQuestionData.answerData[i].Score > 0)
                            {
                                rightAnswer += "C";
                            }
                            break;
                        case 3:
                            if (mQuestionData.answerData[i].Score > 0)
                            {
                                rightAnswer += "D";
                            }
                            break;
                    }
                }
                #endregion
            }
            //选择一个选项之后不能在选择其他选项
            item.thisToggle.interactable = false;
        }

        //题目正确与否的判断
        if (rightAnswer == temp)
        {
            isCorrent = true;
            //把多选的字符串置空
            StringToNull();
            analysisData.text = String.Format("恭喜你,答对啦!");
            GetComponent<AudioSource>().clip = musics[0];
            GetComponent<AudioSource>().Play();
        }
        else
        {
            isCorrent = false;
            //把多选的字符串置空
            StringToNull();
            analysisData.text = String.Format("很遗憾,答错了!正确答案是:{0}\n", rightAnswer);
            //错误音效播放
            GetComponent<AudioSource>().clip = musics[1];
            GetComponent<AudioSource>().Play();
            Invoke("ShowLastRoot", 3);
            defeatImg.gameObject.SetActive(true);

        }

        submitBtn.interactable = false;
        Invoke("nextClick", 3);

        //如果当前题目是最后一题,提交之后,出现提示界面
        if (index + 1 == mQuestionPanelData.questionData.Count)
        {
            Invoke("ShowLastRoot", 3);
        }

        //提交后,该题目不可再选择修改

        submitBtn.interactable = false;
    }

//多选字符串归零
    void StringToNull()
    {
        optionA = "";
        optionB = "";
        optionC = "";
        optionD = "";
    }

3、根据按钮名称获取不同路径的题库

通过获取n个不重复的随机数,设置每个按钮的名称,在根据名称获取对应名称的xml文件,这样每次重新进入盲盒界面的时候,每个按钮的名称不同,获取的xml文件也不同,就实现了随机出题的功能。

string QuestionData1;
    string QuestionText;
    // 开始答题
    public void StartAnswer(ContentBtnItem contentBtnItem)
    {

        //显示和隐藏过度界面
        ShowInterimRoot();
        Invoke("CloseInterimRoot", 3);

        _contentItem = contentBtnItem;
        QuestionData1 = "file://" + Application.dataPath + "/StreamingAssets/" + _contentItem.name + ".xml";
        //QuestionData = _contentItem.QuestionData;
        Debug.Log("btn的名字" + _contentItem.name);
        Debug.Log(QuestionData1);
        QuestionText = "QuestionText";
        StartCoroutine(LoadingQuesiton(QuestionData1));

        for (int i = 0; i < QuestionPanel.questionPanelData.Count; i++)
        {
            InitQuestionPanel(QuestionPanel.questionPanelData[i]);
        }

    }

三:整体代码

Panel_Question

using System;
using System.Collections;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Linq;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 答题的总逻辑
/// </summary>
public class Panel_Question : MonoBehaviour
{
    ContentBtnItem _contentItem;
    [Header("root界面:首界面 开始答题 过度界面 答题界面 结束界面 ")]
    [SerializeField] GameObject firstRoot;
    public GameObject startRoot;
    [SerializeField] GameObject interimRoot;
    [SerializeField] GameObject answerRoot;
    [SerializeField] GameObject endRoot;

    [Header("按钮:前往答题界面按钮 开始答题 上一题,提交,下一题")]
    [SerializeField] Button toStartRootBtn;
    [SerializeField] Button previousBtn;
    [SerializeField] Button submitBtn;
    [SerializeField] Button nextBtn;

    [Header("正确图片,错误图片 题型图片 题型英文图片")]
    [SerializeField] Image correntImg;
    [SerializeField] Image defeatImg;
    [SerializeField] Image QTImg;
    [SerializeField] Image QTEngImg;

    [SerializeField] List<Sprite> QTSprites;

    [Header("文本:题目序号 解析内容 得分 倒计时  最后得分")]
    [SerializeField] Text questionID;
    [SerializeField] Text analysisData;
    [SerializeField] Text countDownTxt;
    [SerializeField] Text endTxt;

    [Header("内容scroll的content 单选scroll的content 选项scroll的content")]
    [SerializeField] Transform contentScrollContent;
    [SerializeField] Transform questionBtnRoot;
    [SerializeField] Transform selectContent;
    [SerializeField] Transform scrollView;

    [SerializeField] ToggleGroup questionGroup;

    [Header("正确音效 错误音效 成功音效 失败音效")]
    [SerializeField] List<AudioClip> musics;
    // 答题界面数据内容
    private QuestionPanelData mQuestionPanelData;
    // 每一道题的题目内容
    private QuestionData mQuestionData;
    // 题目内容物体
    private GameObject mQuestion;
    // 选项的链表
    private List<Options> options = new List<Options>();

    [SerializeField] GameObject prefab;
    private List<int> randomNum = new List<int>();  //存放随机数
    private List<int> randomNum1 = new List<int>();  //存放随机数

    int index = 0;

    [SerializeField] GameObject buttonContent;

    #region 单例和初始化
    static Panel_Question instance;

    public static Panel_Question GetInstance()
    {
        return instance;
    }

    private void Awake()
    {
        Init();
        instance = this;
    }
    #endregion


    #region 按钮监听和获取随机数
    private void Init()
    {
        toStartRootBtn.onClick.AddListener(ToStartRootEvent);
        //previousBtn.onClick.AddListener(previousClick);
        submitBtn.onClick.AddListener(submitClick);
        //nextBtn.onClick.AddListener(nextClick);

        //获取随机数
        GetRandomNum();

        GetBtnRandomNum();
    }
    #endregion

    private void Start()
    {
        //读取xml文件,随机出一套题库
        if (_contentItem == null)
        {
            StartCoroutine(LoadingQuesiton(DataPath.QuestionData));
        }
        else
        {
            StartCoroutine(LoadingQuesiton(QuestionData1));
        }

        //初始界面的显示与隐藏
        firstRoot.SetActive(true);
        startRoot.SetActive(false);
        interimRoot.SetActive(false);
        answerRoot.SetActive(false);
        endRoot.SetActive(false);

        //设置多选字段为空
        StringToNull();

        //默认提交按钮不能使用,没有提交
        submitBtn.interactable = false;
    }
    string[] optionContent;
    string temp;
    string optionA = "";    //存储多选A选项
    string optionB = "";    //存储多选B选项
    string optionC = "";    //存储多选C选项
    string optionD = "";    //存储多选D选项
    bool isSub;     //是否点击了提交按钮
    private void Update()
    {
        //提交按钮是否能使用
        foreach (var item in options)
        {
            //题型图片的设置
            if (mQuestionData.answerData.Count == 4)
            {
                if (mQuestionData.IsSingleChoice)//单选图片
                {
                    QTImg.sprite = QTSprites[0];
                    QTEngImg.sprite = QTSprites[3];
                }
                else                            //多选图片
                {
                    QTImg.sprite = QTSprites[1];
                    QTEngImg.sprite = QTSprites[4];
                }
            }
            else if (mQuestionData.answerData.Count == 2)//判断图片
            {
                QTImg.sprite = QTSprites[2];
                QTEngImg.sprite = QTSprites[5];
            }

            //提取选项
            optionContent = item.optionText.GetComponent<Text>().text.Split('.');

            //题目判断
            if (item.thisToggle.isOn)
            {
                if (!isSub)
                {
                    submitBtn.interactable = true;
                    isSub = true;
                }
                //如果是单选的话,直接把正确答案跟选择的答案比较
                if (mQuestionData.IsSingleChoice)
                {
                    temp = optionContent[0];
                    //Debug.Log("单选" + optionContent[0]);
                    //temp = optionContent[0];
                }
                else
                {
                    if (optionContent[0] == "A")
                        optionA = "A";
                    else if (optionContent[0] == "B")
                        optionB = "B";
                    else if (optionContent[0] == "C")
                        optionC = "C";
                    else if (optionContent[0] == "D")
                        optionD = "D";
                    temp = optionA + optionB + optionC + optionD;
                    //Debug.Log("多选1" + temp);

                }
            }
            else
            {
                if (!mQuestionData.IsSingleChoice)
                {
                    if (optionContent[0] == "A")
                        optionA = "";
                    else if (optionContent[0] == "B")
                        optionB = "";
                    else if (optionContent[0] == "C")
                        optionC = "";
                    else if (optionContent[0] == "D")
                        optionD = "";
                    temp = optionA + optionB + optionC + optionD;
                    //Debug.Log("多选2" + temp);
                }
            }

        }

        if (Input.GetKeyDown(KeyCode.Escape))
        {
            Application.Quit();
            Debug.Log("程序退出");
        }
    }

    #region 读取xml文件
    IEnumerator LoadingQuesiton(string path)
    {
        yield return null;
        using (WWW www = new WWW(path))
        {
            yield return www;
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(www.text);
            new QuestionPanel(doc.FirstChild);

        }
    }
    #endregion

    #region 初始化第一道题
    public void InitQuestionPanel(QuestionPanelData questionPanelData)
    {
        randomNum.Clear();
        GetRandomNum();
        //this.gameObject.SetActive(true);
        mQuestionPanelData = questionPanelData;
        //Debug.Log(randomNum[index]);
        CreateQuestion(questionPanelData.questionData[randomNum[index]]);
    }
    #endregion

    #region 创建题目
    bool isFirst = false;
    public void CreateQuestion(QuestionData questionData)
    {
        //获取随机数
        GetRandomNum();
        //数据赋值
        analysisData.text = "";

        mQuestionData = questionData;
        questionID.text = string.Format("第{0}题(共" + mQuestionPanelData.questionData.Count + "题)", index + 1);
        if (mQuestion != null)
        {
            Destroy(mQuestion);
        }

        //实例化题目预制体
        QuestionText = "QuestionText";
        mQuestion = Instantiate(Resources.Load<GameObject>(QuestionText));
        mQuestion.transform.SetParent(contentScrollContent);
        mQuestion.transform.localScale = Vector3.one;
        mQuestion.GetComponent<Text>().text = questionData.problem;

        if (options.Count > 0)
        {
            for (int i = 0; i < options.Count; i++)
            {
                Destroy(options[i].gameObject);
            }
        }
        options = new List<Options>();

        //实例化按钮选项组序列
        if (!isFirst)
            for (int i = 0; i < mQuestionPanelData.questionData.Count; i++)
            {
                //Instantiate(prefab, scrollView);
                isFirst = true;
            }


        //实例化选项预制体
        for (int i = 0; i < questionData.answerData.Count; i++)
        {
            Options option = Instantiate(Resources.Load<Options>("Options"));
            option.Init(questionData.answerData[i]);
            option.transform.SetParent(selectContent);
            //如果是单选则设置为一个toggle组
            if (questionData.IsSingleChoice)
            {
                option.thisToggle.group = questionGroup;
            }

            options.Add(option);
        }
    }
    #endregion

    #region 前往盲盒界面 开始答题 上一题 下一题  提交按钮事件

    //前往盲盒界面
    void ToStartRootEvent()
    {
        firstRoot.SetActive(false);
        startRoot.SetActive(true);
        interimRoot.SetActive(false);
        answerRoot.SetActive(false);
        endRoot.SetActive(false);
        randomNum1.Clear();
        GetBtnRandomNum();
    }

    #region 开始答题(包含过度界面的显示和关闭)
    string QuestionData1;
    string QuestionText;
    // 开始答题
    public void StartAnswer(ContentBtnItem contentBtnItem)
    {

        //显示和隐藏过度界面
        ShowInterimRoot();
        Invoke("CloseInterimRoot", 3);

        _contentItem = contentBtnItem;
        QuestionData1 = "file://" + Application.dataPath + "/StreamingAssets/" + _contentItem.name + ".xml";
        //QuestionData = _contentItem.QuestionData;
        Debug.Log("btn的名字" + _contentItem.name);
        Debug.Log(QuestionData1);
        QuestionText = "QuestionText";
        StartCoroutine(LoadingQuesiton(QuestionData1));

        for (int i = 0; i < QuestionPanel.questionPanelData.Count; i++)
        {
            InitQuestionPanel(QuestionPanel.questionPanelData[i]);
        }

    }

    //开启过渡界面
    void ShowInterimRoot()
    {
        firstRoot.SetActive(false);
        startRoot.SetActive(false);
        interimRoot.SetActive(true);
        answerRoot.SetActive(false);
        endRoot.SetActive(false);
    }

    //关闭过渡界面
    void CloseInterimRoot()
    {
        firstRoot.SetActive(false);
        startRoot.SetActive(false);
        interimRoot.SetActive(false);
        answerRoot.SetActive(true);
        endRoot.SetActive(false);
    }
    #endregion


    // 下一题事件
    private void nextClick()
    {
        if (index < mQuestionPanelData.questionData.Count - 1)
        {
            index++;
            CreateQuestion(mQuestionPanelData.questionData[randomNum[index]]);
            //isFirstClick = false;
        }

        submitBtn.interactable = false;
        isSub = false;

    }

    bool isCorrent;     //是否全部答对
    string rightAnswer;
    int score = 0;
    // 题目提交事件
    private void submitClick()
    {
        isSub = true;
        //遍历当前题目的选项,有选择的就可以提交核验答案,并显示解析内容
        foreach (var item in options)
        {
            if (item.thisToggle.isOn)
            {
                rightAnswer = "";
                for (int i = 0; i < mQuestionData.answerData.Count; i++)
                {
                    switch (i)
                    {
                        case 0:
                            if (mQuestionData.answerData[i].Score > 0)//xml文档里面score属性对应的数值是用来判断该选项是否为正确选项
                            {
                                rightAnswer += "A";
                            }
                            break;
                        case 1:
                            if (mQuestionData.answerData[i].Score > 0)
                            {
                                rightAnswer += "B";
                            }
                            break;
                        case 2:
                            if (mQuestionData.answerData[i].Score > 0)
                            {
                                rightAnswer += "C";
                            }
                            break;
                        case 3:
                            if (mQuestionData.answerData[i].Score > 0)
                            {
                                rightAnswer += "D";
                            }
                            break;
                    }
                }
                #endregion
            }
            //选择一个选项之后不能在选择其他选项
            item.thisToggle.interactable = false;
        }

        //题目正确与否的判断
        if (rightAnswer == temp)
        {
            isCorrent = true;
            //把多选的字符串置空
            StringToNull();
            analysisData.text = String.Format("恭喜你,答对啦!");
            GetComponent<AudioSource>().clip = musics[0];
            GetComponent<AudioSource>().Play();
        }
        else
        {
            isCorrent = false;
            //把多选的字符串置空
            StringToNull();
            analysisData.text = String.Format("很遗憾,答错了!正确答案是:{0}\n", rightAnswer);
            //错误音效播放
            GetComponent<AudioSource>().clip = musics[1];
            GetComponent<AudioSource>().Play();
            Invoke("ShowLastRoot", 3);
            defeatImg.gameObject.SetActive(true);

        }

        submitBtn.interactable = false;
        Invoke("nextClick", 3);

        //如果当前题目是最后一题,提交之后,出现提示界面
        if (index + 1 == mQuestionPanelData.questionData.Count)
        {
            Invoke("ShowLastRoot", 3);
        }

        //提交后,该题目不可再选择修改

        submitBtn.interactable = false;
    }

    //返回主界面
    void BackToMain()
    {
        //返回主界面
        firstRoot.SetActive(true);
        startRoot.SetActive(false);
        interimRoot.SetActive(false);
        answerRoot.SetActive(false);
        endRoot.SetActive(false);


        index = 0;
    }

    //显示结束界面
    void ShowLastRoot()
    {
        //界面的显示
        firstRoot.SetActive(false);
        startRoot.SetActive(false);
        interimRoot.SetActive(false);
        answerRoot.SetActive(false);
        endRoot.SetActive(true);

        //如果答对显示正确界面,答错显示错误界面
        if (isCorrent)
        {
            correntImg.gameObject.SetActive(true);
            defeatImg.gameObject.SetActive(false);
            GetComponent<AudioSource>().clip = musics[2];
            GetComponent<AudioSource>().Play();
        }
        else
        {
            correntImg.gameObject.SetActive(false);
            defeatImg.gameObject.SetActive(true);
            GetComponent<AudioSource>().clip = musics[3];
            GetComponent<AudioSource>().Play();
        }

        //延迟3秒返回主界面
        Invoke("BackToMain", 5);
    }

    //多选字符串归零
    void StringToNull()
    {
        optionA = "";
        optionB = "";
        optionC = "";
        optionD = "";
    }

    #region 随机顺序出题
    void GetRandomNum()
    {
        //利用哈希函数获取随机数
        HashSet<int> nums = new HashSet<int>();
        System.Random r = new System.Random();
        while (nums.Count != 6)
        {
            nums.Add(r.Next(0, 6));
        }
        //Debug.Log(topicMax);
        foreach (var item in nums)
        {
            randomNum.Add(item);
        }
    }

    public void GetBtnRandomNum()
    {
        //利用哈希函数获取随机数
        HashSet<int> nums = new HashSet<int>();
        System.Random r = new System.Random();
        while (nums.Count != 9)
        {
            nums.Add(r.Next(0, 9));
        }
        //Debug.Log(topicMax);
        foreach (var item in nums)
        {
            randomNum1.Add(item);
        }
        for (int i = 0; i < buttonContent.transform.childCount; i++)
        {
            buttonContent.transform.GetChild(i).name = randomNum1[i].ToString();
        }
    }

    #endregion

    #region 程序退出
    public void ExitGame()
    {
        Application.Quit();
        Debug.Log("程序退出");
    }
    #endregion

}

#region 答题数据类
/// <summary>
/// 答题panel数据类
/// </summary>
public class QuestionPanel
{
    public static List<QuestionPanelData> questionPanelData;
    public QuestionPanel(XmlNode node)
    {
        questionPanelData = new List<QuestionPanelData>();
        for (int i = 0; i < node.ChildNodes.Count; i++)
        {
            questionPanelData.Add(new QuestionPanelData(node.ChildNodes[i]));
            //Debug.Log(questionPanelData);
        }
    }
}

/// <summary>
/// 答题界面数据类
/// </summary>
public class QuestionPanelData
{
    public List<QuestionData> questionData;
    public QuestionPanelData(XmlNode node)
    {
        questionData = new List<QuestionData>();
        for (int i = 0; i < node.ChildNodes.Count; i++)
        {
            questionData.Add(new QuestionData(node.ChildNodes[i]));
        }
    }
}

/// <summary>
/// 题目数据类
/// </summary>
public class QuestionData
{
    // 是否为单选,true为单选,false为多选
    private bool isSingleChoice;
    // 解析内容
    public string Analysis;
    // 题目内容
    public string problem;
    public List<AnswerData> answerData;

    public bool IsSingleChoice { get => isSingleChoice; set => isSingleChoice = value; }

    public QuestionData(XmlNode node)
    {
        isSingleChoice = bool.Parse(node.Attributes["SelectType"].InnerText);
        Analysis = node["Analysis"].InnerText;
        problem = node["Problem"].InnerText;
        answerData = new List<AnswerData>();
        XmlNodeList nodelist = node["Answer"].ChildNodes;
        for (int i = 0; i < nodelist.Count; i++)
        {
            answerData.Add(new AnswerData(nodelist[i]));
        }
    }
}

/// <summary>
/// 答案数据类
/// </summary>
public class AnswerData
{
    // 选项的内容
    public string option;
    // 选项对应的分数
    public int Score;
    public AnswerData(XmlNode node)
    {
        option = node.Attributes["option"].InnerText;
        Score = int.Parse(node.InnerText);
    }
}
#endregion

ContentBtnItem挂在每个盲盒按钮上

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 按钮点击事件
/// </summary>
public class ContentBtnItem : MonoBehaviour
{
    Button btn;
    public string QuestionData;
    public static string QuestionText;
    void Start()
    {
        btn = GetComponent<Button>();
        
        QuestionText = "QuestionText";
        btn.onClick.AddListener(delegate { Panel_Question.GetInstance().StartAnswer(this); });
    }

    // Update is called once per frame
    void Update()
    {

    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 全局静态类,用来定义静态字段,方便调用
/// </summary>
public class DataPath
{
    public static string QuestionData = "file://" + Application.dataPath + "/StreamingAssets/0.xml";

    //public static string QuestionData;
    public static string QuestionText = "QuestionText";

}

 Options选项预制体身上挂这个

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Options : MonoBehaviour
{
    /// <summary>
    /// 当前选项组件
    /// </summary>
    public Toggle thisToggle;
    /// <summary>
    /// 选项的内容文本
    /// </summary>
    public Text optionText;
    /// <summary>
    /// 选项对应的分数
    /// </summary>
    public int score;
    /// <summary>
    /// 选项的状态
    /// </summary>
    public bool IsSelect = false;

    public void Init(AnswerData answerData)
    {
        optionText.text = answerData.option;
        score = answerData.Score;
        thisToggle.onValueChanged.AddListener((isSelect) => { IsSelect =isSelect; });
    }
}

四:效果展示

九宫格盲盒演示视频

猜你喜欢

转载自blog.csdn.net/shijinlinaaa/article/details/132674482