hello, I am currently working on an rpg, in it I have a quest manager where I have an array of quest objects that have start and end mission triggers, the problem is that these triggers are activated even when the previous mission has not been completed, I need to know how I can disable array objects and enable them as they are completed (start with an array of 0 to 2, where quest object 0 is enabled and 1 and 2 are disabled, once 0 is completed, 1 is enabled, once 1 is completed, 2 is enabled)
This is the questManager code:
public QuestObject[] quests;
public bool[] questsCompleted;
public DialogManager DM;
public string itemCollected;
// Start is called before the first frame update
void Start()
{
questsCompleted = new bool[quests.Length];
}
// Update is called once per frame
void Update()
{
}
public void ShowQuestText(string questText)
{
DM.dialogLines = new string[1];
DM.dialogLines[0] = questText;
DM.currentLine = 0;
DM.ShowDialogue();
}
This is the QuestObject code:
public int questNumber;
public QuestManager QM;
public string startText;
public string endText;
public bool isItemQuest;
public string targetItem;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if(isItemQuest)
{
if (QM.itemCollected == targetItem)
{
QM.itemCollected = null;
EndQuest();
}
}
}
public void StartQuest()
{
QM.ShowQuestText(startText);
}
public void EndQuest()
{
QM.questsCompleted[questNumber] = true;
gameObject.SetActive(false);
QM.ShowQuestText(endText);
}
And this is the triggers code:
private QuestManager QM;
public int questNumber;
public bool startQuest;
public bool endQuest;
// Start is called before the first frame update
void Start()
{
QM = FindObjectOfType<QuestManager>();
}
// Update is called once per frame
void Update()
{
}
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.gameObject.name == "Player")
{
if(!QM.questsCompleted[questNumber])
{
if(startQuest && QM.quests[questNumber].gameObject.activeSelf)
{
QM.quests[questNumber].gameObject.SetActive(true);
QM.quests[questNumber].StartQuest();
}
if(endQuest && QM.quests[questNumber].gameObject.activeSelf)
{
QM.quests[questNumber].EndQuest();
}
}
}
}
The reference way to do this in Unity is to list them all in a master controlling list, then on Awake iterate that list and set them all to .SetActive(false).
Now you can activate one at a time, turning all the others off.
Things to watch out for: in the quest scripts, don’t do anything in Awake() or OnEnable() that you don’t mind happening when a quest might be off. In other words, use Start() so that the script is disabled before its Start() gets called.
This can help you visualize the timing on the Awake, OnEnable, Start, etc. methods:
And you can make a simple index select only one item to turn on with a construct like this:
int which = (put whatever number you want into which);
for (int i = 0; i < Quests.Length; i++)
{
// only the one matching i == which will be on, all others will be off
Quests[i].SetActive( i == which);
}
int which = (put whatever number you want into which);
for (int i = 0; i < Quests.Length; i++)
{
// only the one matching i == which will be on, all others will be off
Quests[i].SetActive( i == which);
}
like this
deactivateAllQuests();
activateQuest(3);
(Edit: it’s not exactly the same thing, but the difference is negligible.)
where
void deactivateAllQuests() {
for(int i = 0; i < Quests.Length; i++)
Quests[i].SetActive(false);
}
void activateQuest(int index) {
Quests[index].SetActive(true);
}
Hopefully you can now improvise yourself.
For example