- Home /
Array of scripts
I've got a script on a game object and I want it hold an Array of other scripts on the same game object. I thought this might be a good way of storing MMO style quests as each quest can have its own script and its own rules and functions.
I've tried declaring the array as Component[] and it lets me drag the scripts into the array in the inspector but it wont let me call any functions on the quest script because it says "x is not a member of component"
Is there a way to store scripts in an array which lets you access functions in specific scripts? I thought about using SendMessage but it would be called on every single script in the game object which might slow the game down if there are hundreds of quests.
Is there a better way to manage quests?
Answer by fherbst · Jun 15, 2010 at 09:02 AM
Your question reminded me of something in my programming class - type polymorphism! And I was curious whether this can be used in Unity. So I took the time to put it together.
The idea is to have a basic quest class:
using UnityEngine; using System.Collections;
// BaseQuest derives from MonoBehaviour, so it can be added to GameObjects
// abstract means: this class does not implement any functions, it only says which functions // must be implemented in derived classes public abstract class BaseQuest : MonoBehaviour { // here we have the basic quest behaviour - each derived class knows what to do with this function public abstract string QuestText(); }
This script is never actually added to any GameObject, its just the base for other quest scripts:
A simple quest:
using UnityEngine; using System.Collections;
// a simple quest is a quest - so it derives from the BaseQuest class public class SimpleQuest : BaseQuest { void Start () {}
// the "old" QuestText method from BaseQuest gets overwritten
public override string QuestText()
{
return ("I am a simple quest!");
}
}
A more advanced quest:
using UnityEngine; using System.Collections;
// an advanced quest is a quest - so it derives from the BaseQuest class public class AdvancedQuest : BaseQuest { void Start () {}
// the "old" QuestText method from BaseQuest gets overwritten
public override string QuestText()
{
return ("I am an advanced quest!");
}
}
Right now, you can add the AdvancedQuest and SimpleQuest scripts to a GameObject as many times as you want. Now comes the script that handles everything:
using UnityEngine; using System.Collections; using System.Collections.Generic;
public class QuestHandler : MonoBehaviour {
// This list handles all the quests
private List<BaseQuest> quests;
void Start ()
{
// the quests list gets created
quests = new List<BaseQuest>();
// collecting all the quests from the GameObject (the player)
Component[] questsComps = gameObject.GetComponents(typeof(BaseQuest));
foreach(Component comp in questsComps)
{
// adding the quest to the list
addQuest(comp as BaseQuest);
}
// each quest shows his message
foreach (BaseQuest quest in quests)
// here comes the magic - type polymorphism!
// all quests in the list derive from BaseQuest, which has this function
// all the derived quests override the QuestText function with their own behaviour
Debug.Log(quest.QuestText());
}
void addQuest(BaseQuest q)
{
// adding the quest to the list
quests.Add(q);
}
}
It gets added to the same GameObject. On Start(), it collects all the scripts of BaseQuest class and all its derivates (this was were I wasn't sure Unity would handle it in this (right) way). All the quests get added to a quests List of BaseQuest objects.
And then every quest is asked to return its QuestText - and due to the type polymorphism, the right QuestText method is chosen and executed.
Thanks for this cool question!
That's a good way of handling quests lists but it would be difficult to be sure of the order that the quests appear in the list. For instance if you wanted to update a single quest script you'd have to do a search through the list each time you wanted to do an update. The only alternative would be to set a public array and drag every script into the inspector. It's an interesting solution though.
The List class is ordered, so maybe one could use that. There can even custom Sort-methods be defined. And as (with this way) each quest is a $$anonymous$$onoBehaviour resting on the GameObject, they expose their properties to the editor and do things like Update() and all the other stuff. Thanks you like the solution!
Ins$$anonymous$$d of using a list, you might want to try using a Dictionary, as then you can look up quests by name ins$$anonymous$$d of number
Answer by Lucas Meijer 1 · May 04, 2010 at 07:07 AM
Best I can think off right now is to have remember which quests to use by their name. string[] quests. It doesn't give a great UI experience out of the box (you cannot drag quest scripts onto them), however that is a great excuse to write a custom inspector, where you can drag quests scripts onto it, which will then in turn just read the name from the script, and add it to the stringarray. At runtime, you can get at the .net type of your script using Type.GetType("BigAssDragonQuest");
Thanks for the answer, now if there were a way to use the string to call another script, I dunno if GetComponent will do it..
You can. You could use System.Activator to create an instance a script by name.
What if the script is already on the game object? If each trigger instantiates a new script it wouldn't be tracking the state changes.
Your answer
Follow this Question
Related Questions
How do I get multiplayer to my game? 1 Answer
How To Make A Simple MMO? 3 Answers
RPG turns system - arranging turns freezes up 1 Answer
RPG controller 1 Answer
Looking for a chat text box that allows voice chat... 0 Answers