Unity答题系统
文章目錄
- 答題系統(tǒng)Demo前言
- 準備工作
- 搭建答題系統(tǒng)界面UI
- 將題庫xml文件存放在自己創(chuàng)建的XML文件夾下
- 編寫腳本實現(xiàn)答題系統(tǒng)相關功能
- Panel_Question.cs腳本掛載到主界面Panel_Question上
- Options.cs腳本掛載的選項預制體上,管理每一個選項的數(shù)據(jù)
- 答題系統(tǒng)demo演示
- 額外的知識
答題系統(tǒng)Demo前言
大四畢設的時候,參考網(wǎng)上大佬的答題系統(tǒng),移植到了我的畢設項目中去,總感覺那個答題系統(tǒng)不夠滿意,但是那會技術有限,沒有去深入研究完善,而且總有bug,后面答辯后也沒管了。工作了,學的東西多了點,琢磨著自己也搞個答題系統(tǒng)玩玩,這個demo用的是加載XML文檔的方法創(chuàng)建題目,xml文檔中可以設置題目是單選還是多選。有上一題、下一題的功能,每一題都有提交功能,只有選擇了答案才能提交,提交了會顯示題目的解析。能滿足一般的答題系統(tǒng)的需求了。
準備工作
搭建答題系統(tǒng)界面UI
如圖所示:
其中題目選項和解析內容使用滾動視圖(scroll view)來規(guī)范顯示內容。這里還需要在滾動視圖的content物體上添加自動布局的組件:設置垂直布局自適應。
注意:
在使用滾動視圖的地方,將content作為父物體的,都要在content物體上添加自動布局組件,并在子元素自適應,不然你會看到生成的題目有可能飛到十萬八千里之外,那這樣在視圖里面就看不到了。
將題庫xml文件存放在自己創(chuàng)建的XML文件夾下
xml文檔內容格式如下:
編寫腳本實現(xiàn)答題系統(tǒng)相關功能
Panel_Question.cs腳本掛載到主界面Panel_Question上
public class Panel_Question : MonoBehaviour {/// <summary>/// 上一題按鈕/// </summary>private Button previousBtn;/// <summary>/// 提交按鈕/// </summary>private Button submitBtn;/// <summary>/// 下一題按鈕/// </summary>private Button nextBtn;/// <summary>/// 當前是第幾道題/// </summary>private Text questionID;/// <summary>/// 解析內容文本/// </summary>private Text analysisData;/// <summary>/// 題目的父節(jié)點/// </summary>private Transform questionRoot;private Transform questionBtnRoot;/// <summary>/// 選項的組/// </summary>private ToggleGroup questionGroup;/// <summary>/// 答題界面數(shù)據(jù)內容/// </summary>private QuestionPanelData mQuestionPanelData;/// <summary>/// 每一道題的題目內容/// </summary>private QuestionData mQuestionData;/// <summary>/// 題目內容物體/// </summary>private GameObject mQuestion;/// <summary>/// 題目計數(shù)/// </summary>private int mQuestionCount;/// <summary>/// 選項的鏈表/// </summary>private List<Options> options=new List<Options>();private void Awake(){Init();}/// <summary>/// 初始化找到相關物體和組件,并給按鈕添加監(jiān)聽方法/// </summary>private void Init(){previousBtn = transform.Find("BGImage/topic/btn_Previous").GetComponent<Button>();submitBtn= transform.Find("BGImage/topic/btn_Submit").GetComponent<Button>();nextBtn= transform.Find("BGImage/topic/btn_Next").GetComponent<Button>();questionID = transform.Find("BGImage/topic/questionNumber").GetComponent<Text>();analysisData= transform.Find("BGImage/analysis/Scroll View/Viewport/Content/Text").GetComponent<Text>();questionRoot = transform.Find("BGImage/topic/Scroll View/Viewport/Content").transform;questionBtnRoot= transform.Find("BGImage/selectSign/Viewport/Content").transform;questionGroup = transform.Find("BGImage/topic/Scroll View/Viewport/Content").GetComponent<ToggleGroup>();previousBtn.onClick.AddListener(previousClick);submitBtn.onClick.AddListener(submitClick);nextBtn.onClick.AddListener(nextClick);}private void Start(){StartCoroutine(LoadingQuesiton(DataPath.QuestionData));}/// <summary>/// 點擊開始答題事件,將解析好的題目內容初始化顯示出來/// </summary>public void StartAnswer(){for (int i = 0; i < QuestionPanel.questionPanelData.Count; i++){InitQuestionPanel(QuestionPanel.questionPanelData[i]);}}/// <summary>/// 加載xml文件的協(xié)程/// </summary>/// <param name="path">文件路徑</param>/// <returns></returns>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);}}/// <summary>/// 初始化第一道題/// </summary>/// <param name="questionPanelData"></param>public void InitQuestionPanel(QuestionPanelData questionPanelData){//this.gameObject.SetActive(true);mQuestionCount = 0;mQuestionPanelData = questionPanelData;CreateQuestion(questionPanelData.questionData[mQuestionCount]);}/// <summary>/// 創(chuàng)建題目/// </summary>/// <param name="questionData"></param>private void CreateQuestion(QuestionData questionData){analysisData.text = "";mQuestionData = questionData;questionID.text = string.Format("第{0}題", mQuestionCount + 1);if (mQuestion!=null){Destroy(mQuestion);}//實例化題目預制體mQuestion = GameObject.Instantiate(Resources.Load<GameObject>(DataPath.QuestionText));mQuestion.transform.SetParent(questionRoot);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>();//實例化選項預制體for (int i = 0; i < questionData.answerData.Count; i++){Options option = GameObject.Instantiate(Resources.Load<Options>("Options"));option.Init(questionData.answerData[i]);option.transform.SetParent(questionRoot);//如果是單選則設置為一個toggle組if (questionData.isSingleChoice){option.thisToggle.group = questionGroup;}options.Add(option);}}/// <summary>/// 上一題點擊事件/// </summary>private void previousClick(){if (mQuestionCount>0){mQuestionCount--;CreateQuestion(mQuestionPanelData.questionData[mQuestionCount]);}}/// <summary>/// 下一題點擊事件/// </summary>private void nextClick(){if (mQuestionCount<mQuestionPanelData.questionData.Count-1){mQuestionCount++;CreateQuestion(mQuestionPanelData.questionData[mQuestionCount]);}}private string rightAnswer;/// <summary>/// 提交事件/// </summary>private void submitClick(){//遍歷當前題目的選項,有選擇的就可以提交核驗答案,并顯示解析內容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屬性對應的數(shù)值是用來判斷該選項是否為正確選項{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;}}analysisData.text = String.Format("正確選項是:{0}\n解析:{1}", rightAnswer, mQuestionData.Analysis);}}} } /// <summary> /// 答題界面數(shù)據(jù)類 /// </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]));}} } /// <summary> /// 答題界面數(shù)據(jù)類 /// </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> /// 題目數(shù)據(jù)類 /// </summary> public class QuestionData {/// <summary>/// 是否為單選,true為單選,false為多選/// </summary>public bool isSingleChoice;/// <summary>/// 解析內容/// </summary>public string Analysis;/// <summary>/// 題目內容/// </summary>public string problem;public List<AnswerData> answerData;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> /// 答案數(shù)據(jù)類 /// </summary> public class AnswerData {/// <summary>/// 選項的內容/// </summary>public string option;/// <summary>/// 選項對應的分數(shù)/// </summary>public int Score;public AnswerData(XmlNode node){option = node.Attributes["option"].InnerText;Score = int.Parse(node.InnerText);}}DataPath.cs全局靜態(tài)類:
Options.cs腳本掛載的選項預制體上,管理每一個選項的數(shù)據(jù)
public class Options : MonoBehaviour {/// <summary>/// 當前選項組件/// </summary>public Toggle thisToggle;/// <summary>/// 選項的內容文本/// </summary>public Text optionText;/// <summary>/// 選項對應的分數(shù)/// </summary>public int score;/// <summary>/// 選項的狀態(tài)/// </summary>public bool IsSelect=false;public void Init(AnswerData answerData){optionText.text = answerData.option;score = answerData.Score;thisToggle.onValueChanged.AddListener((isSelect) => { IsSelect = isSelect; });} }答題系統(tǒng)demo演示
單選:
多選:
選錯:
這個答題系統(tǒng)滿足了基本的單選多選需求,后期可以考慮完善其他功能…
額外的知識
demo用到的Application.dataPath指的是程序的數(shù)據(jù)文件所在的文件夾路徑,這里是因為在PC平臺使用www類加載資源,所以加載路徑要使用file://協(xié)議實現(xiàn)加載,否則會加載失敗。平臺不一樣,路徑也不一樣。
執(zhí)行以下代碼:
① Yield return null,在此表示暫緩一幀,在下一幀才執(zhí)行后面的代碼,等同于yield return +任意數(shù)字,yield return www表示等待資源加載完成,再執(zhí)行后面的代碼,等同于www.isDone.
② using語句在此處的作用是,使用了www類的實例,結束的時候自動調用Dispose處理實例對象。即將其釋放掉。
③ Unity里加載xml文件的一般流程是:引入System.Xml命名空間,寫加載解析的函數(shù),函數(shù)里先創(chuàng)建xml文檔的對象:XmlDocument doc=new XmlDocument();,再通過調用XmlNodeList、XmlNode、XmlElement等類的屬性和方法去遍歷查找并讀取相關的節(jié)點數(shù)據(jù)。
④ Xml類常用的一些類和方法:
其中Load()方法是指可以從 一個指定的文件中解析內容,而LoadXml()則是加載有xml格式字符串到DOM對象中。
總結
- 上一篇: show open tables命令 m
- 下一篇: 微信团队分享:微信移动端的全文检索多音字