一、原版修改
1、导入资源
Unity Learn | 3D Beginner: Complete Project | URP
2、设置Scene
删除SampleScene,打开UnityTechnologies-3DBeginnerComplete下的MainScene
3、降低音量
(1) 打开Hierarchy面板上的Audio降低音量
(2) 打开Prefabs文件夹,找到Ghost,降低音量
4、给FaderCanvas添加组件
(1) Canvas Scaler
(2) Graphic Raycaster
二、新增收集事件
1、新增物体
(1) 新增物体:UI-Image。Questions。设置它的Rect Transform。
(2) 新增文本:ItemsText, TipText(可设置有透明度的黑色背景)
2、新建CollectedItems.cs
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;public class CollectedItems : MonoBehaviour
{public QuestionCollision QuestionCollision;//public GameObject Questions;public TextMeshProUGUI ItemsText, TipText;static int nucleus=0, mitochondria = 0, GolgiApparatus = 0, endoplasmicReticulum = 0, ribosome = 0;void Start(){if (ItemsText == null || TipText == null){Debug.LogError("Questions或ItemsText 或 TipText 未被正确分配!");}}private void OnTriggerEnter(Collider other){if (other.CompareTag("Player")){RandomEvent();}}public void RandomEvent(){int numericValue = Random.Range(0, 100);if (numericValue < 5 && nucleus==0){nucleus = 1;TipText.text = "你发现了细胞核!";}else if(numericValue < 26){mitochondria++;TipText.text = "你得到了线粒体!";}else if (numericValue < 41){endoplasmicReticulum++;TipText.text = "你得到了内质网*1!";}else if (numericValue < 56){GolgiApparatus++;TipText.text = "你得到了高尔基体*1!";}else if (numericValue < 76){ribosome++;TipText.text = "你得到了核糖体*1!";}else if (numericValue < 86){QuestionCollision.ShowQuestions(true);//Questions.SetActive(true);}else{TipText.text = "你什么都没有发现……";}ItemsUpdate();}void ItemsUpdate(){ItemsText.text = "当前持有:细胞核" + nucleus + ";线粒体" + mitochondria + ";高尔基体" + GolgiApparatus + ";内质网" + endoplasmicReticulum + ";核糖体" + ribosome;}
}
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.UI;
using static UnityEngine.Rendering.DebugUI;public class Observer : MonoBehaviour
{public Exercises exercises;public Transform player;public GameObject Questions;public TextMeshProUGUI ItemsText, TipText;static int nucleus=0, mitochondria = 0, GolgiApparatus = 0, endoplasmicReticulum = 0, ribosome = 0;bool canTriggerEffect = true;void OnTriggerEnter(Collider other){if (other.CompareTag("Player")) // 玩家的标签为 "Player" {exercises.ShowQuestion(0);RandomEvent(); }}public void QuitBtn() {GetComponent<UnityEngine.UI.Button>().gameObject.SetActive(false);Questions.SetActive(false);}void ItemsUpdate(){ItemsText.text ="当前持有:细胞核" + nucleus + ";线粒体" + mitochondria + ";高尔基体" + GolgiApparatus + ";内质网" + endoplasmicReticulum + ";核糖体" + ribosome;}void Start(){if (ItemsText == null || TipText == null){Debug.LogError("ItemsText 或 TipText 未被正确分配!");}}void RandomEvent(){if (canTriggerEffect){// 触发效果代码int numericValue = UnityEngine.Random.Range(0, 100);if (numericValue < 5 && nucleus == 0)//获取的随机数范围在0~4{nucleus = 1;TipText.text = "你发现了细胞核!";StartCoroutine(ClearTextRoutine(2f));print("随机数" + numericValue);}else if (numericValue < 21){mitochondria++;TipText.text = "你得到了线粒体!";StartCoroutine(ClearTextRoutine(2f));print("随机数" + numericValue);}else if (numericValue < 41){endoplasmicReticulum++;TipText.text = "你得到了内质网*1!";StartCoroutine(ClearTextRoutine(2f));print("随机数" + numericValue);}else if (numericValue < 61){GolgiApparatus++;TipText.text = "你得到了高尔基体*1!";StartCoroutine(ClearTextRoutine(2f));print("随机数" + numericValue);}else if (numericValue < 81){ribosome++;TipText.text = "你得到了核糖体*1!"; StartCoroutine(ClearTextRoutine(2f));print("随机数" + numericValue);}else if (numericValue < 96){Questions.SetActive(true);}else{TipText.text = "你什么都没有发现……";StartCoroutine(ClearTextRoutine(2f));print("随机数" + numericValue);}//gameEnding.CaughtPlayer ();ItemsUpdate();canTriggerEffect = false; // 触发效果,将canTriggerEffect设置为falseStartCoroutine(CooldownRoutine()); // 启动冷却时间协程}}IEnumerator CooldownRoutine(){yield return new WaitForSeconds(60f); // 等待1分钟canTriggerEffect = true; // 冷却结束,可以再次触发效果}IEnumerator ClearTextRoutine(float delay){yield return new WaitForSeconds(delay);TipText.text = "";}
}
3、更改enemy设置
(1) 复制 PointOfView预制体,得到PointOfView(1),更名为CollectedItems
(2) 移除CollectedItems上的Observer.cs,添加CollectedItems.cs
(3) 删除Hierarchy面板上的除Ghost (3)以外的敌人的PointOfView。添加CollectedItems预制体并赋值
三、编辑答题面板预制体
1、设置面板
(1) UI-Image,命名为Questions。
(2) 选中导入的图片,然后在Inspector面板中将Texture Type设置为Sprite (2D and UI)
(3) 更改Questions的Image,Transform
(4) 添加按钮,QuitBtn(以隐藏答题面板)
2、添加test
(1) 添加文本。TitleText
(2) 添加按钮。OptionBtnA,按钮下文本的名字OptionTextA,更改文字字体,复制这个按钮得到四个选项按钮
(3) 将Questions制成预制体
(4) 制作题目
3、建立题库——简单题库
A. 创建ChoiceQuestion.cs(不用挂载的脚本)可以与其他脚本放在一起
定义问题类(包含一个问题(question
字段)、四个选项(options
数组)和正确答案的索引(correctOptionIndex
字段))
using System.Collections;
using System.Collections.Generic;
using UnityEngine;[System.Serializable]
public class Question
{public string question; // 问题文本public string[] options = new string[4]; // 选项数组,假设每个问题都有4个选项public int correctOptionIndex; // 正确答案的索引(0表示A,1表示B,依此类推)// 构造函数(可选),用于初始化问题public Question(string q, string[] opts, int correctIndex){question = q;options = opts;correctOptionIndex = correctIndex;}// 检查答案是否正确public bool CheckAnswer(int playerChoice){return playerChoice == correctOptionIndex;}
}
B. 在一个空物体上添加Exercises.cs,控制显示题目和选项、正误判断、答题后禁用按钮
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;public class Exercises : MonoBehaviour
{public Database_01 Database_01;//题库脚本public TextMeshProUGUI questionText;public Button[] optionButtons;private int currentQuestionIndex = 0; // 初始化当前问题索引为0public void ShowQuestion(int index){if (index >= 0 && index < Database_01.questionsDatabase.Count)//如果index在questionsDatabase列表的有效范围内{// 显示题目(从列表中取出索引为index的问题,并将其文本内容显示在questionText的文本组件上)questionText.text = Database_01.questionsDatabase[index].question;// 显示选项(将Database_01中当前问题的选项文本显示在optionButtons数组或列表中的相应UI元素上)for (int i = 0; i < Database_01.questionsDatabase[index].options.Length; i++){optionButtons[i].GetComponentInChildren<TextMeshProUGUI>().text = Database_01.questionsDatabase[index].options[i];}}}// 选项按钮的点击事件public void OnOptionButtonClicked(int buttonIndex){foreach (var button in optionButtons){button.interactable = false; // 设置为false以禁用按钮}// currentQuestionIndex:当前显示的问题的索引// 检查用户选择的答案是否正确bool isCorrect = Database_01.questionsDatabase[currentQuestionIndex].CheckAnswer(buttonIndex);// 根据检查结果执行相应的操作,比如更新UI、显示消息等if (isCorrect){Debug.Log("回答正确!");currentQuestionIndex++; // 更新当前问题索引}else{Debug.Log("回答错误!");}}
}
C.给空物体添加Database_01.cs,以建立题库
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Database_01 : MonoBehaviour
{public List<Question> questionsDatabase = new List<Question>(); // 选择题数据库void Start(){// 初始化选择题数据库InitializeQuestions();}void InitializeQuestions(){//添加一个问题到数据库questionsDatabase.Add(new Question("…………是?",new string[] { "A. ……", "B. ……", "C. ……", "D. ……" },0 // 假设"选项A"是正确答案,所以索引是0));//添加一个问题到数据库questionsDatabase.Add(new Question("…………",new string[] { "A. 复杂性", "B. 多样性", "C. 统一性", "D. 稳定性" },2 // 假设"选项C"是正确答案,所以索引是2));}
}
4、建立题库——导入txt文本的方式
(1) 加载文本
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using TMPro;
using UnityEngine;public class QuizManager : MonoBehaviour
{private Question currentQuestion;//存储当前展示的题目private List<Question> questionList;public TextMeshProUGUI questionTextComponent; // 用于显示题干的Text组件public TextMeshProUGUI optionATextComponent; // 用于显示选项A的Text组件public TextMeshProUGUI optionBTextComponent; // 用于显示选项B的Text组件public TextMeshProUGUI optionCTextComponent; // 用于显示选项C的Text组件public TextMeshProUGUI optionDTextComponent; // 用于显示选项D的Text组件void Start(){questionList = new List<Question>();LoadQuestionsFromTxt("QuestionBank.txt");GetRandomQuestion();}//加载文本文件void LoadQuestionsFromTxt(string filename){// 组合文件的完整路径。Application.streamingAssetsPath是Unity的一个属性,// 指向StreamingAssets文件夹的路径string filePath = Path.Combine(Application.streamingAssetsPath, filename);// 检查文件是否存在if (File.Exists(filePath)){// 使用File.OpenText来打开文件,并创建一个StreamReader来读取内容using (StreamReader reader = File.OpenText(filePath)){// 声明一个字符串变量line,用于存储从文件中读取的每一行内容string line;// 逐行读取文件内容,直到读取到文件末尾while ((line = reader.ReadLine()) != null){// 使用 | 分隔每一行的内容string[] data = line.Split('|');// 检查是否至少有6个由竖线分隔的值(问题、四个选项和答案)if (data.Length < 6){Debug.LogError("Invalid line format in question file: " + line);continue; // 跳过这一行,继续读取下一行}// 从分割后的数组中提取问题、选项和答案string question = data[0];string optionA = "A. " + data[1];string optionB = "B. " + data[2];string optionC = "C. " + data[3];string optionD = "D. " + data[4];string answer = data[5].ToUpper();// 检查答案是否在给定的选项中if (!IsValidAnswer(answer, optionA, optionB, optionC, optionD)){Debug.LogError("Invalid answer in question file: " + line);continue; // 跳过这一行,继续读取下一行}// 创建一个新的Question对象,并将其添加到questionList列表中Question newQuestion = new Question(question, optionA, optionB, optionC, optionD, answer.ToUpper());questionList.Add(newQuestion);}}}else{Debug.LogError("Cannot find question file: " + filename);}}// 检查答案是否在给定的选项列表中bool IsValidAnswer(string answer, string optionA, string optionB, string optionC, string optionD){//StringComparison.OrdinalIgnoreCase:确保比较时不区分大小写return answer.Equals("A", StringComparison.OrdinalIgnoreCase) ||answer.Equals("B", StringComparison.OrdinalIgnoreCase) ||answer.Equals("C", StringComparison.OrdinalIgnoreCase) ||answer.Equals("D", StringComparison.OrdinalIgnoreCase);}//从题目列表中随机选择一个题目,并将其赋值给currentQuestion变量public void GetRandomQuestion(){if (questionList.Count == 0){Debug.LogError("No questions to display.");return;}int randomIndex = UnityEngine.Random.Range(0, questionList.Count);currentQuestion = questionList[randomIndex];questionList.RemoveAt(randomIndex);// 从列表中移除问题,防止重复}void UpdateQuestionDisplay(){// 分别设置各个Text组件的text属性questionTextComponent.text = currentQuestion.QuestionText;optionATextComponent.text = currentQuestion.OptionAText;optionBTextComponent.text = currentQuestion.OptionBText;optionCTextComponent.text = currentQuestion.OptionCText;optionDTextComponent.text = currentQuestion.OptionDText;}void OnUserAnswer(){// 处理用户答题后的操作// 获取下一个随机题目GetRandomQuestion();// 更新问题展示UpdateQuestionDisplay();}
}
// 定义一个名为Question的类,用于存储问题及其相关信息
[Serializable]
public class Question
{public string QuestionText;public string OptionAText;public string OptionBText;public string OptionCText;public string OptionDText;public string Answer; // 注意这里不需要ToUpper(),除非您有特定的需求public Question(string question, string optionA, string optionB, string optionC, string optionD, string answer){QuestionText = question;OptionAText = optionA;OptionBText = optionB;OptionCText = optionC;OptionDText = optionD;Answer = answer;}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using TMPro;
using UnityEngine;public class QuizManager : MonoBehaviour
{private Question currentQuestion;//存储当前展示的题目private List<Question> questionList;public TextMeshProUGUI questionText;void Start(){questionList = new List<Question>();LoadQuestionsFromTxt("QuestionBank.txt");GetRandomQuestion();}//加载文本文件void LoadQuestionsFromTxt(string filename){// 组合文件的完整路径。Application.streamingAssetsPath是Unity的一个属性,// 指向StreamingAssets文件夹的路径string filePath = Path.Combine(Application.streamingAssetsPath, filename);// 检查文件是否存在if (File.Exists(filePath)){// 使用File.OpenText来打开文件,并创建一个StreamReader来读取内容using (StreamReader reader = File.OpenText(filePath)){// 声明一个字符串变量line,用于存储从文件中读取的每一行内容string line;// 逐行读取文件内容,直到读取到文件末尾while ((line = reader.ReadLine()) != null){// 使用 | 分隔每一行的内容string[] data = line.Split('|');// 检查是否至少有6个由竖线分隔的值(问题、四个选项和答案)if (data.Length < 6){Debug.LogError("Invalid line format in question file: " + line);continue; // 跳过这一行,继续读取下一行}// 从分割后的数组中提取问题、选项和答案string question = data[0];string optionA = "A. " + data[1];string optionB = "B. " + data[2];string optionC = "C. " + data[3];string optionD = "D. " + data[4];string answer = data[5].ToUpper();// 检查答案是否在给定的选项中if (!IsValidAnswer(answer, optionA, optionB, optionC, optionD)){Debug.LogError("Invalid answer in question file: " + line);continue; // 跳过这一行,继续读取下一行}// 创建一个新的Question对象,并将其添加到questionList列表中Question newQuestion = new Question(question, optionA, optionB, optionC, optionD, answer.ToUpper());questionList.Add(newQuestion);}}}else{Debug.LogError("Cannot find question file: " + filename);}}// 检查答案是否在给定的选项列表中bool IsValidAnswer(string answer, string optionA, string optionB, string optionC, string optionD){//StringComparison.OrdinalIgnoreCase:确保比较时不区分大小写return answer.Equals("A", StringComparison.OrdinalIgnoreCase) ||answer.Equals("B", StringComparison.OrdinalIgnoreCase) ||answer.Equals("C", StringComparison.OrdinalIgnoreCase) ||answer.Equals("D", StringComparison.OrdinalIgnoreCase);}//从题目列表中随机选择一个题目,并将其赋值给currentQuestion变量public void GetRandomQuestion(){if (questionList.Count == 0){Debug.LogError("No questions to display.");return;}int randomIndex = UnityEngine.Random.Range(0, questionList.Count);currentQuestion = questionList[randomIndex];questionList.RemoveAt(randomIndex);// 从列表中移除问题,防止重复string displayText = currentQuestion.QuestionText + "\n" + // 假设Question类有一个QuestionText属性currentQuestion.OptionAText + "\n" + // 类似地,其他选项和答案也需要有相应的属性currentQuestion.OptionBText + "\n" +currentQuestion.OptionCText + "\n" +currentQuestion.OptionDText;questionText.text = displayText;}void UpdateQuestionDisplay(){// 将currentQuestion的问题文本赋值// 将currentQuestion的问题文本赋值给questionText的text属性questionText.text = currentQuestion.QuestionText;}void OnUserAnswer(){// 处理用户答题后的操作// 获取下一个随机题目GetRandomQuestion();// 更新问题展示UpdateQuestionDisplay();}
}// 定义一个名为Question的类,用于存储问题及其相关信息
[Serializable]
public class Question
{public string QuestionText;public string OptionAText;public string OptionBText;public string OptionCText;public string OptionDText;public string Answer; // 注意这里不需要ToUpper(),除非您有特定的需求public Question(string question, string optionA, string optionB, string optionC, string optionD, string answer){QuestionText = question;OptionAText = optionA;OptionBText = optionB;OptionCText = optionC;OptionDText = optionD;Answer = answer;}
}
(1)
(2) QuestionBank.txt
文件位于Unity项目的StreamingAssets
文件夹中,并且格式正确(即每行都有六个由 | 分隔的值)答案用ABCD表示
(3)
(4)
4、设置调用test
(1) 给JohnLemon添加PlayerQuest.cs
5、判断正误
6、生命值脚本
using UnityEngine;public class PlayerHealth : MonoBehaviour
{public int maxLives = 3;private int currentLives;private void Start(){currentLives = maxLives;}public void AddLife(){if (currentLives < maxLives){currentLives++;}}public void LoseLife(){if (currentLives > 0){currentLives--;}else{Debug.Log("角色死亡!退出游戏");}}
}
7、问题面板显示和隐藏脚本
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;public class QuestionCollision : MonoBehaviour
{public GameObject questionPanel;//问题面板public Button QuitBtn;public TextMeshProUGUI questionText;//问题文本public Button[] optionBtns;public PlayerHealth playerHealth;public void ShowQuestions(bool isQuestionActivated){if (isQuestionActivated){questionPanel.SetActive(true);}else{questionPanel.SetActive(false);}foreach (Button button in optionBtns){button.onClick.AddListener(()=> CheckAnswer(button));}}public void OnClickQuitBtn(){questionPanel.SetActive(false);}void Start(){questionPanel.SetActive(false);}private void CheckAnswer(Button button){if (button.CompareTag("CorrectAnswer")){playerHealth.AddLife();}questionPanel.SetActive(false);}
}
public List<Transform> bodyList = new List<Transform>();public GameObject bodyPrefab;public Sprite[] bodySprites = new Sprite[2];//数组中只含有2张图片private Transform canvas;private void Awake(){canvas = GameObject.Find("Canvas").transform;//找到Canvas的Transform}void BodyCreate(){//如果bodyList的元素数量是偶数,Index将被赋值为0。如果bodyList的元素数量是奇数,Index将被赋值为1int Index = (bodyList.Count % 2 == 0) ? 0 : 1;//bodyList.Count:列表中的元素数量(生成几种物体)//bodyList.Count % 2:元素数量除以2,的余数//bodyList.Count % 2 == 0:检查余数是否是0(是0,说明元素数量是偶数)//? 0 : 1:如果元素数量是偶数(余数是0)则整个表达式的值是0。否则是1GameObject body = Instantiate(bodyPrefab,new Vector3(2000,2000,0),Quaternion.identity);//生成预制体在看不到的位置body.GetComponent<UnityImage>().sprite = bodySprites[Index];//从bodySprites数组中获取位于Index位置的图片body.transform.SetParent(canvas, false);//使Canvas成为body的父物体,而不使用它的世界坐标bodyList.Add(body.transform);}
ItemsBackground,ItemsText,TipText
九、暂存
1、隐藏按钮
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class ButtonHideObjectController : MonoBehaviour
{public GameObject objectToHide; // 在Inspector中设置这个引用void Start(){// 获取Button组件Button button = GetComponent<Button>();if (button != null){// 添加点击事件监听器button.onClick.AddListener(HideObject);Debug.Log(button.interactable);}}// 点击按钮时调用的方法public void HideObject(){if (objectToHide != null){objectToHide.SetActive(false); // 隐藏物体}}
}
2、含有构造函数的问题组成设置
using System.Collections;
using System.Collections.Generic;
using UnityEngine;[System.Serializable]
public class Question
{public string question; // 问题文本public string[] options = new string[4]; // 选项数组,假设每个问题都有4个选项public int correctOptionIndex; // 正确答案的索引(0表示A,1表示B,依此类推)// 构造函数(可选),用于初始化问题public Question(string q, string[] opts, int correctIndex){question = q;options = opts;correctOptionIndex = correctIndex;}// 检查答案是否正确public bool CheckAnswer(int playerChoice){return playerChoice == correctOptionIndex;}
}
3、题库脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Database_01 : MonoBehaviour
{public List<Question> questionsDatabase = new List<Question>(); // 选择题数据库void Start(){// 初始化选择题数据库InitializeQuestions();}void InitializeQuestions(){//添加一个问题到数据库questionsDatabase.Add(new Question("生命系统最基本的结构层次是?",new string[] { "A. 细胞", "B. 组织", "C. 器官", "D. 系统" },0 // 假设"选项A"是正确答案,所以索引是0));//添加一个问题到数据库questionsDatabase.Add(new Question("细胞学说揭示了动物和植物的",new string[] { "A. 复杂性", "B. 多样性", "C. 统一性", "D. 稳定性" },2 // 假设"选项C"是正确答案,所以索引是2));}
}
4、显示题目并判断对错
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;public class Exercises : MonoBehaviour
{public Database_01 Database_01;//题库脚本public TextMeshProUGUI questionText;public Button[] optionButtons;private int currentQuestionIndex = 0; // 初始化当前问题索引为0public void ShowQuestion(int index){if (index >= 0 && index < Database_01.questionsDatabase.Count)//如果index在questionsDatabase列表的有效范围内{// 显示题目(从列表中取出索引为index的问题,并将其文本内容显示在questionText的文本组件上)questionText.text = Database_01.questionsDatabase[index].question;// 显示选项(将Database_01中当前问题的选项文本显示在optionButtons数组或列表中的相应UI元素上)for (int i = 0; i < Database_01.questionsDatabase[index].options.Length; i++){optionButtons[i].GetComponentInChildren<TextMeshProUGUI>().text = Database_01.questionsDatabase[index].options[i];}}}// 选项按钮的点击事件public void OnOptionButtonClicked(int buttonIndex){foreach (var button in optionButtons){button.interactable = false; // 设置为false以禁用按钮}// currentQuestionIndex:当前显示的问题的索引// 检查用户选择的答案是否正确bool isCorrect = Database_01.questionsDatabase[currentQuestionIndex].CheckAnswer(buttonIndex);// 根据检查结果执行相应的操作,比如更新UI、显示消息等if (isCorrect){Debug.Log("回答正确!");currentQuestionIndex++; // 更新当前问题索引}else{Debug.Log("回答错误!");}}
}
5、退出
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;public class GameEnding : MonoBehaviour
{public float fadeDuration = 1f;public float displayImageDuration = 1f;public GameObject player;public CanvasGroup exitBackgroundImageCanvasGroup;public AudioSource exitAudio;public CanvasGroup caughtBackgroundImageCanvasGroup;public AudioSource caughtAudio;bool m_IsPlayerAtExit;bool m_IsPlayerCaught;float m_Timer;bool m_HasAudioPlayed;void OnTriggerEnter (Collider other){if (other.gameObject == player){m_IsPlayerAtExit = true;}}public void CaughtPlayer (){m_IsPlayerCaught = true;}void Update (){if (m_IsPlayerAtExit){EndLevel (exitBackgroundImageCanvasGroup, false, exitAudio);}else if (m_IsPlayerCaught){EndLevel (caughtBackgroundImageCanvasGroup, true, caughtAudio);}}void EndLevel (CanvasGroup imageCanvasGroup, bool doRestart, AudioSource audioSource){if (!m_HasAudioPlayed){audioSource.Play();m_HasAudioPlayed = true;}m_Timer += Time.deltaTime;imageCanvasGroup.alpha = m_Timer / fadeDuration;if (m_Timer > fadeDuration + displayImageDuration){if (doRestart){SceneManager.LoadScene (0);}else{Application.Quit ();}}}
}
6、获取物体
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.UI;
using static UnityEngine.Rendering.DebugUI;public class Observer : MonoBehaviour
{public Exercises exercises;public Transform player;public GameObject Questions;public TextMeshProUGUI ItemsText, TipText;static int nucleus=0, mitochondria = 0, GolgiApparatus = 0, endoplasmicReticulum = 0, ribosome = 0;bool canTriggerEffect = true;void OnTriggerEnter(Collider other){if (other.CompareTag("Player")) // 玩家的标签为 "Player" {exercises.ShowQuestion(0);RandomEvent(); }}public void QuitBtn() {GetComponent<UnityEngine.UI.Button>().gameObject.SetActive(false);Questions.SetActive(false);}void ItemsUpdate(){ItemsText.text ="当前持有:细胞核" + nucleus + ";线粒体" + mitochondria + ";高尔基体" + GolgiApparatus + ";内质网" + endoplasmicReticulum + ";核糖体" + ribosome;}void Start(){if (ItemsText == null || TipText == null){Debug.LogError("ItemsText 或 TipText 未被正确分配!");}}void RandomEvent(){if (canTriggerEffect){// 触发效果代码int numericValue = UnityEngine.Random.Range(0, 100);if (numericValue < 5 && nucleus == 0)//获取的随机数范围在0~4{nucleus = 1;TipText.text = "你发现了细胞核!";StartCoroutine(ClearTextRoutine(2f));print("随机数" + numericValue);}else if (numericValue < 21){mitochondria++;TipText.text = "你得到了线粒体!";StartCoroutine(ClearTextRoutine(2f));print("随机数" + numericValue);}else if (numericValue < 41){endoplasmicReticulum++;TipText.text = "你得到了内质网*1!";StartCoroutine(ClearTextRoutine(2f));print("随机数" + numericValue);}else if (numericValue < 61){GolgiApparatus++;TipText.text = "你得到了高尔基体*1!";StartCoroutine(ClearTextRoutine(2f));print("随机数" + numericValue);}else if (numericValue < 81){ribosome++;TipText.text = "你得到了核糖体*1!"; StartCoroutine(ClearTextRoutine(2f));print("随机数" + numericValue);}else if (numericValue < 96){Questions.SetActive(true);}else{TipText.text = "你什么都没有发现……";StartCoroutine(ClearTextRoutine(2f));print("随机数" + numericValue);}//gameEnding.CaughtPlayer ();ItemsUpdate();canTriggerEffect = false; // 触发效果,将canTriggerEffect设置为falseStartCoroutine(CooldownRoutine()); // 启动冷却时间协程}}IEnumerator CooldownRoutine(){yield return new WaitForSeconds(60f); // 等待1分钟canTriggerEffect = true; // 冷却结束,可以再次触发效果}IEnumerator ClearTextRoutine(float delay){yield return new WaitForSeconds(delay);TipText.text = "";}
}
7、