I'm currently developing a game in C# with Unity and I designed some Quizzes for the Player.
It has a Manager-Script which is called from a trigger. I made 5 NPC-Characters who are triggering the Quizzes if the Player is nearby, but they are using the same trigger and manager-script. I would like to make a method which checks, if one Quiz was already answered correctly, while not blocking the Quizzes from other NPCs. I tried with a bool, but then I could answer the Quiz from NPC1, but the Quiz from NPC2 was already "marked" as answered correctly as well.
This is my Manager-Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using Ink.Runtime;
using UnityEngine.EventSystems;
using Unity.Netcode;
using Unity.Netcode.Transports.UTP;
public class NPCQuizManager : MonoBehaviour
{
[Header("Dialog UI")]
[SerializeField] private GameObject dialogPanel;
[SerializeField] private TextMeshProUGUI dialogText;
[Header("Choices UI")]
[SerializeField] private GameObject[] choices;
private TextMeshProUGUI[] choiceTexts;
private Story currentStory;
public bool dialogIsActive{get; private set;}
private static NPCQuizManager instance;
private int rightChoice;
HealthManager hpLoss;
public GameObject player;
private void Awake(){
if(instance != null){
Debug.LogWarning("Es gibt mehrere Dialog Manager in der Scene!");
}
instance = this;
}
public static NPCQuizManager GetInstance(){
if(instance == null){
instance = new NPCQuizManager();
}
return instance;
}
private void Start(){
dialogIsActive = false;
dialogPanel.SetActive(false);
choiceTexts = new TextMeshProUGUI[choices.Length];
int index = 0;
foreach(GameObject choice in choices){
choiceTexts[index] = choice.GetComponentInChildren<TextMeshProUGUI>();
index ;
}
}
private void Update(){
if(dialogIsActive){
if(Input.GetKeyDown(KeyCode.E)){
ContinueStory();
}
}
}
public void StartDialog(TextAsset inkJSON, int correctChoice){
rightChoice = correctChoice;
currentStory = new Story(inkJSON.text);
dialogIsActive = !dialogIsActive;
dialogPanel.SetActive(dialogIsActive);
ContinueStory();
}
public void ExitDialogeMode(){
dialogIsActive = false;
dialogPanel.SetActive(false);
dialogText.text = "";
}
private void ContinueStory(){
if(currentStory.canContinue){
// Setze DialogText auf den nächsten Knoten
dialogText.text = currentStory.Continue();
// Zeige die Choices an
DisplayChoices();
}
else{
//ExitDialogeMode();
}
}
private void DisplayChoices(){
List<Choice> currentChoices = currentStory.currentChoices;
//Check if there are more choices than UI elements
if(currentChoices.Count > choices.Length){
Debug.LogWarning("Es gibt mehr Choices als UI Elemente! Es werden nur: " currentChoices.Count " angezeigt!");
}
int index = 0;
//Display all choices
foreach(Choice choice in currentChoices){
choices[index].SetActive(true);
choiceTexts[index].text = choice.text;
index ;
}
// Hide all unused choices
for(int i = index; i < choices.Length; i ){
choices[i].SetActive(false);
}
StartCoroutine(SelectFirstChoice());
}
private IEnumerator SelectFirstChoice(){
//Das Eventsystem muss auf null gesetzt werden, damit es nicht mehr auf das letzte UI Element zeigt
EventSystem.current.SetSelectedGameObject(null);
yield return new WaitForEndOfFrame();
EventSystem.current.SetSelectedGameObject(choices[0].gameObject);
}
public void chooseChoice(int choiceIndex){
currentStory.ChooseChoiceIndex(choiceIndex);
if(choiceIndex == rightChoice){
AddECTS();
}
else{
looseHP();
}
ContinueStory();
}
public void AddECTS(){
player = GameObject.FindGameObjectWithTag("Player");
player.GetComponent<ECTSCounter>().erhoeheWert(5);
}
public void looseHP(){
hpLoss = GameObject.Find("Healthbar").GetComponent<HealthManager>();
hpLoss.TakeDamage(2);
}
}
I would appreciate and help :-)
CodePudding user response:
You could use a bit flag or bool array to save the answered question
private bool[] answered = new bool[numberOfQuestions];
private bool AlreadyAnswered(int questionIndex){
return answered[questionIndex];
}
CodePudding user response:
Instead of marking a quiz answered I'd create a dictionary of players as heys and quizzes ids as values that stores who has taken part in which quiz:
private static Dictionary<GameObject, int> _quizzesParticipationTracing = new Dictionary<GameObject, int>();
// I see that your 'player' is of type GameObject,
// but you can use any other unique reference to the player,
// e.g. the UID, if available.
Then, each time a player appears near the quiz, you check whether they already exist in the dictionary and which quizzes they participated in. And then you either display an available quiz or inform them that there aren't any quizzes available.
Does this make sense to you?