Unity3D實(shí)戰(zhàn)之答題系統(tǒng)的實(shí)現(xiàn)
一、前言
這是本專(zhuān)欄系列的第一篇,答題系統(tǒng)的開(kāi)發(fā)。
這個(gè)答題系統(tǒng),可以從文本文檔中提取題目和分?jǐn)?shù),然后綁定到UI上,在答題的過(guò)程中,自動(dòng)判斷分?jǐn)?shù),自動(dòng)判斷正確率。
目的是實(shí)現(xiàn)一個(gè)可快速導(dǎo)入到項(xiàng)目中使用的小模塊。
二、效果圖及工程下載

題目文檔 密碼:1234
三、實(shí)現(xiàn)
1.界面搭建
首先,新建工程,然后擺UI,如下圖所示:

2.讀取文檔
題目存放在txt文檔中,首先,我們看一下結(jié)構(gòu):

每一行都是一道題目,然后題號(hào)、題目、選項(xiàng)、得分,都是用冒號(hào)進(jìn)行分割的。
下一步就需要用腳本進(jìn)行讀取文檔了。
新建腳本Answer.cs:編寫(xiě)代碼:
讀取文檔:
using System.Collections.Generic;
using UnityEngine;
public class Answer : MonoBehaviour
{
//讀取文檔
string[][] ArrayX;
string[] lineArray;
private int topicMax = 0;//最大題數(shù)
private List<bool> isAnserList = new List<bool>();//存放是否答過(guò)題的狀態(tài)
void Start()
{
TextCsv();
}
/*****************讀取txt數(shù)據(jù)******************/
void TextCsv()
{
//讀取csv二進(jìn)制文件
TextAsset binAsset = Resources.Load("YW", typeof(TextAsset)) as TextAsset;
//讀取每一行的內(nèi)容
lineArray = binAsset.text.Split('\r');
//創(chuàng)建二維數(shù)組
ArrayX = new string[lineArray.Length][];
//把csv中的數(shù)據(jù)儲(chǔ)存在二維數(shù)組中
for (int i = 0; i < lineArray.Length; i++)
{
ArrayX[i] = lineArray[i].Split(':');
}
//查看保存的題目數(shù)據(jù)
for (int i = 0; i < ArrayX.Length; i++)
{
for (int j = 0; j < ArrayX[i].Length; j++)
{
Debug.Log(ArrayX[i][j]);
}
}
//設(shè)置題目狀態(tài)
topicMax = lineArray.Length;
for (int x = 0; x < topicMax + 1; x++)
{
isAnserList.Add(false);
}
}
}
可以看到,所有的題目數(shù)據(jù)都讀取出來(lái)了:

3.加載題目
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Answer : MonoBehaviour
{
//讀取文檔
string[][] ArrayX;//題目數(shù)據(jù)
string[] lineArray;//讀取到題目數(shù)據(jù)
private int topicMax = 0;//最大題數(shù)
private List<bool> isAnserList = new List<bool>();//存放是否答過(guò)題的狀態(tài)
//加載題目
public GameObject tipsbtn;//提示按鈕
public Text tipsText;//提示信息
public List<Toggle> toggleList;//答題Toggle
public Text indexText;//當(dāng)前第幾題
public Text TM_Text;//當(dāng)前題目
public List<Text> DA_TextList;//選項(xiàng)
private int topicIndex = 0;//第幾題
void Start()
{
TextCsv();
LoadAnswer();
}
/*****************讀取txt數(shù)據(jù)******************/
void TextCsv()
{
//讀取csv二進(jìn)制文件
TextAsset binAsset = Resources.Load("YW", typeof(TextAsset)) as TextAsset;
//讀取每一行的內(nèi)容
lineArray = binAsset.text.Split('\r');
//創(chuàng)建二維數(shù)組
ArrayX = new string[lineArray.Length][];
//把csv中的數(shù)據(jù)儲(chǔ)存在二維數(shù)組中
for (int i = 0; i < lineArray.Length; i++)
{
ArrayX[i] = lineArray[i].Split(':');
}
//設(shè)置題目狀態(tài)
topicMax = lineArray.Length;
for (int x = 0; x < topicMax + 1; x++)
{
isAnserList.Add(false);
}
}
/*****************加載題目******************/
void LoadAnswer()
{
tipsbtn.SetActive(false);
tipsText.text = "";
for (int x = 0; x < 4; x++)
{
toggleList[x].isOn = false;
}
indexText.text = "第" + (topicIndex + 1) + "題:";//第幾題
TM_Text.text = ArrayX[topicIndex][1];//題目
int idx = ArrayX[topicIndex].Length - 3;//有幾個(gè)選項(xiàng)
for (int x = 0; x < idx; x++)
{
DA_TextList[x].text = ArrayX[topicIndex][x + 2];//選項(xiàng)
}
}
}

題目正常加載:

4.按鈕功能
/*****************按鈕功能******************/
void Select_Answer(int index)
{
switch (index)
{
case 0://提示
int idx = ArrayX[topicIndex].Length - 1;
int n = int.Parse(ArrayX[topicIndex][idx]);
string nM = "";
switch (n)
{
case 1:
nM = "A";
break;
case 2:
nM = "B";
break;
case 3:
nM = "C";
break;
case 4:
nM = "D";
break;
}
tipsText.text = "<color=#FFAB08FF>" +"正確答案是:"+ nM + "</color>";
break;
case 1://上一題
if (topicIndex > 0)
{
topicIndex--;
LoadAnswer();
}
else
{
tipsText.text = "<color=#27FF02FF>" + "前面已經(jīng)沒(méi)有題目了!" + "</color>";
}
break;
case 2://下一題
if (topicIndex < topicMax-1)
{
topicIndex++;
LoadAnswer();
}
else
{
tipsText.text = "<color=#27FF02FF>" + "哎呀!已經(jīng)是最后一題了。" + "</color>";
}
break;
case 3://跳轉(zhuǎn)
int x = int.Parse(jumpInput.text) - 1;
if (x >= 0 && x < topicMax)
{
topicIndex = x;
jumpInput.text = "";
LoadAnswer();
}
else
{
tipsText.text = "<color=#27FF02FF>" + "不在范圍內(nèi)!" + "</color>";
}
break;
}
}5.題目對(duì)錯(cuò)判斷
/*****************題目對(duì)錯(cuò)判斷******************/
void AnswerRightRrongJudgment(bool check,int index)
{
if (check)
{
//判斷題目對(duì)錯(cuò)
bool isRight;
int idx = ArrayX[topicIndex].Length - 1;
int n = int.Parse(ArrayX[topicIndex][idx]) - 1;
if (n == index)
{
tipsText.text = "<color=#27FF02FF>" + "恭喜你,答對(duì)了!" + "</color>";
isRight = true;
tipsbtn.SetActive(true);
}
else
{
tipsText.text = "<color=#FF0020FF>" + "對(duì)不起,答錯(cuò)了!" + "</color>";
isRight = false;
tipsbtn.SetActive(true);
}
//正確率計(jì)算
if (isAnserList[topicIndex])
{
tipsText.text = "<color=#FF0020FF>" + "這道題已答過(guò)!" + "</color>";
}
else
{
anserint++;
if (isRight)
{
isRightNum++;
}
isAnserList[topicIndex] = true;
TextAccuracy.text = "正確率:" + ((float)isRightNum / anserint * 100).ToString("f2") + "%";
}
//禁用掉選項(xiàng)
for (int i = 0; i < toggleList.Count; i++)
{
toggleList[i].interactable = false;
}
}
}
將按鈕對(duì)象拖進(jìn)卡槽中,運(yùn)行程序即可:

完整代碼如下:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Answer : MonoBehaviour
{
//讀取文檔
string[][] ArrayX;//題目數(shù)據(jù)
string[] lineArray;//讀取到題目數(shù)據(jù)
private int topicMax = 0;//最大題數(shù)
private List<bool> isAnserList = new List<bool>();//存放是否答過(guò)題的狀態(tài)
//加載題目
public GameObject tipsbtn;//提示按鈕
public Text tipsText;//提示信息
public List<Toggle> toggleList;//答題Toggle
public Text indexText;//當(dāng)前第幾題
public Text TM_Text;//當(dāng)前題目
public List<Text> DA_TextList;//選項(xiàng)
private int topicIndex = 0;//第幾題
//按鈕功能及提示信息
public Button BtnBack;//上一題
public Button BtnNext;//下一題
public Button BtnTip;//消息提醒
public Button BtnJump;//跳轉(zhuǎn)題目
public InputField jumpInput;//跳轉(zhuǎn)題目
public Text TextAccuracy;//正確率
private int anserint = 0;//已經(jīng)答過(guò)幾題
private int isRightNum = 0;//正確題數(shù)
void Awake()
{
TextCsv();
LoadAnswer();
}
void Start()
{
toggleList[0].onValueChanged.AddListener((isOn) => AnswerRightRrongJudgment(isOn,0));
toggleList[1].onValueChanged.AddListener((isOn) => AnswerRightRrongJudgment(isOn,1));
toggleList[2].onValueChanged.AddListener((isOn) => AnswerRightRrongJudgment(isOn,2));
toggleList[3].onValueChanged.AddListener((isOn) => AnswerRightRrongJudgment(isOn,3));
BtnTip.onClick.AddListener(() => Select_Answer(0));
BtnBack.onClick.AddListener(() => Select_Answer(1));
BtnNext.onClick.AddListener(() => Select_Answer(2));
BtnJump.onClick.AddListener(() => Select_Answer(3));
}
/*****************讀取txt數(shù)據(jù)******************/
void TextCsv()
{
//讀取csv二進(jìn)制文件
TextAsset binAsset = Resources.Load("YW", typeof(TextAsset)) as TextAsset;
//讀取每一行的內(nèi)容
lineArray = binAsset.text.Split('\r');
//創(chuàng)建二維數(shù)組
ArrayX = new string[lineArray.Length][];
//把csv中的數(shù)據(jù)儲(chǔ)存在二維數(shù)組中
for (int i = 0; i < lineArray.Length; i++)
{
ArrayX[i] = lineArray[i].Split(':');
}
//設(shè)置題目狀態(tài)
topicMax = lineArray.Length;
for (int x = 0; x < topicMax + 1; x++)
{
isAnserList.Add(false);
}
}
/*****************加載題目******************/
void LoadAnswer()
{
for (int i = 0; i < toggleList.Count; i++)
{
toggleList[i].isOn = false;
}
for (int i = 0; i < toggleList.Count; i++)
{
toggleList[i].interactable = true;
}
tipsbtn.SetActive(false);
tipsText.text = "";
indexText.text = "第" + (topicIndex + 1) + "題:";//第幾題
TM_Text.text = ArrayX[topicIndex][1];//題目
int idx = ArrayX[topicIndex].Length - 3;//有幾個(gè)選項(xiàng)
for (int x = 0; x < idx; x++)
{
DA_TextList[x].text = ArrayX[topicIndex][x + 2];//選項(xiàng)
}
}
/*****************按鈕功能******************/
void Select_Answer(int index)
{
switch (index)
{
case 0://提示
int idx = ArrayX[topicIndex].Length - 1;
int n = int.Parse(ArrayX[topicIndex][idx]);
string nM = "";
switch (n)
{
case 1:
nM = "A";
break;
case 2:
nM = "B";
break;
case 3:
nM = "C";
break;
case 4:
nM = "D";
break;
}
tipsText.text = "<color=#FFAB08FF>" +"正確答案是:"+ nM + "</color>";
break;
case 1://上一題
if (topicIndex > 0)
{
topicIndex--;
LoadAnswer();
}
else
{
tipsText.text = "<color=#27FF02FF>" + "前面已經(jīng)沒(méi)有題目了!" + "</color>";
}
break;
case 2://下一題
if (topicIndex < topicMax-1)
{
topicIndex++;
LoadAnswer();
}
else
{
tipsText.text = "<color=#27FF02FF>" + "哎呀!已經(jīng)是最后一題了。" + "</color>";
}
break;
case 3://跳轉(zhuǎn)
int x = int.Parse(jumpInput.text) - 1;
if (x >= 0 && x < topicMax)
{
topicIndex = x;
jumpInput.text = "";
LoadAnswer();
}
else
{
tipsText.text = "<color=#27FF02FF>" + "不在范圍內(nèi)!" + "</color>";
}
break;
}
}
/*****************題目對(duì)錯(cuò)判斷******************/
void AnswerRightRrongJudgment(bool check,int index)
{
if (check)
{
//判斷題目對(duì)錯(cuò)
bool isRight;
int idx = ArrayX[topicIndex].Length - 1;
int n = int.Parse(ArrayX[topicIndex][idx]) - 1;
if (n == index)
{
tipsText.text = "<color=#27FF02FF>" + "恭喜你,答對(duì)了!" + "</color>";
isRight = true;
tipsbtn.SetActive(true);
}
else
{
tipsText.text = "<color=#FF0020FF>" + "對(duì)不起,答錯(cuò)了!" + "</color>";
isRight = false;
tipsbtn.SetActive(true);
}
//正確率計(jì)算
if (isAnserList[topicIndex])
{
tipsText.text = "<color=#FF0020FF>" + "這道題已答過(guò)!" + "</color>";
}
else
{
anserint++;
if (isRight)
{
isRightNum++;
}
isAnserList[topicIndex] = true;
TextAccuracy.text = "正確率:" + ((float)isRightNum / anserint * 100).ToString("f2") + "%";
}
//禁用掉選項(xiàng)
for (int i = 0; i < toggleList.Count; i++)
{
toggleList[i].interactable = false;
}
}
}
}
四、后言
整體來(lái)看,只使用了一個(gè)場(chǎng)景,一個(gè)腳本,就完成了答題系統(tǒng)。
步驟如下:
1、讀取文檔
2、解析文檔保存數(shù)據(jù)
3、根據(jù)數(shù)據(jù)加載題目
4、上一題下一題,選項(xiàng)選擇,跳轉(zhuǎn),按鈕的功能實(shí)現(xiàn)
代碼還是延期了一貫的簡(jiǎn)潔風(fēng)格,希望你可以在這篇文章學(xué)到東西。
以上就是Unity3D實(shí)戰(zhàn)之答題系統(tǒng)的實(shí)現(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于Unity3D答題系統(tǒng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#用websocket實(shí)現(xiàn)簡(jiǎn)易聊天功能(服務(wù)端)
這篇文章主要為大家詳細(xì)介紹了C#用websocket實(shí)現(xiàn)簡(jiǎn)易聊天功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
C#利用RabbitMQ實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)消息傳輸
RabbitMQ做為消息代理,負(fù)責(zé)接收和轉(zhuǎn)發(fā)消息,可以將RabbitMQ比喻為一個(gè)郵筒、一個(gè)郵局和一個(gè)郵遞員。本文主要以一個(gè)簡(jiǎn)單的小例子,簡(jiǎn)述RabbitMQ實(shí)現(xiàn)消息傳輸?shù)南嚓P(guān)內(nèi)容,僅供學(xué)習(xí)分享使用,如有不足之處,還請(qǐng)指正。2021-05-05
基于C#實(shí)現(xiàn)Windows服務(wù)的方法詳解
在實(shí)際應(yīng)用過(guò)程中,有時(shí)候我們希望開(kāi)發(fā)的程序,不需要界面,直接開(kāi)機(jī)就可以長(zhǎng)時(shí)間運(yùn)行,這時(shí)候,我們可以考慮做成一個(gè)Windows服務(wù)。這篇文章跟大家介紹一下,如何基于C#實(shí)現(xiàn)Windows服務(wù)的創(chuàng)建、安裝、啟動(dòng)、停止和卸載,需要的可以參考一下2022-09-09
C# WebApi Get請(qǐng)求方式傳遞實(shí)體參數(shù)的方法示例
這篇文章主要給大家介紹了關(guān)于C# WebApi Get請(qǐng)求方式傳遞實(shí)體參數(shù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C#具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
C#調(diào)用C++動(dòng)態(tài)庫(kù)接口函數(shù)和回調(diào)函數(shù)方法
這篇文章主要介紹了C#調(diào)用C++動(dòng)態(tài)庫(kù)接口函數(shù)和回調(diào)函數(shù)方法,通過(guò)C++端編寫(xiě)接口展開(kāi)內(nèi)容,文章介紹詳細(xì)具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-03-03
C#判斷網(wǎng)站是否能訪(fǎng)問(wèn)或者斷鏈的方法
這篇文章主要介紹了C#判斷網(wǎng)站是否能訪(fǎng)問(wèn)或者斷鏈的方法,實(shí)例分析了C#判斷網(wǎng)站是否能訪(fǎng)問(wèn)的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07
C#操作SQLite數(shù)據(jù)庫(kù)方法小結(jié)(創(chuàng)建,連接,插入,查詢(xún),刪除等)
這篇文章主要介紹了C#操作SQLite數(shù)據(jù)庫(kù)方法,包括針對(duì)SQLite數(shù)據(jù)庫(kù)的創(chuàng)建,連接,插入,查詢(xún),刪除等操作,并提供了一個(gè)SQLite的封裝類(lèi),需要的朋友可以參考下2016-07-07
C#實(shí)現(xiàn)設(shè)置或屏蔽熱鍵的方法詳解
這篇文章主要為大家詳細(xì)介紹了如何利用C#實(shí)現(xiàn)設(shè)置或屏蔽熱鍵,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以跟隨小編一起了解一下2022-12-12

