How to reference a script without having to specify its type

Hello, I keep running into a problem that is making my code ugly. My game is structured so that I have a generic “engine” script that runs on all of the games levels, and a series of scripts that have the data specific to that level. Both of these scripts sit on a game object. It’s easy for me to reference variables when i go from the level level script to the engine, but it is very ugly for me to have to go in the other direction. Here is how I must do it.

in the engine.js:

var stageType:String = "D";
function Start(){

if(stageType=="D")

var levelScript_d:stage_d = gameObject.GetComponent("stage_d");
levelScript_d.doSomething();

}else if(stageType=="F"){

var levelScript_f:stage_f = gameObject.GetComponent("stage_f");
levelScript_f.doSomething();

}

}

I can’t use something like:

var levelScript

on the engine and drag the script onto it because you always have to have the script type in order to do this. Is there a simple way to clean this up so I can always just have a reference to script data.

I want it to look like this:

var levelScript = gameObject.GetComponent("stage_d");
levelScript.doSomething();

…which returns ‘doSomething’ is not a member of ‘UnityEngine.Component’.

Also I realize the minor inefficiencies of the scripts above, but this is just to paint a picture of what I’m looking for. I also realize that the answer is “then don’t structure your game like that.”…but this is something that I’m just interested in knowing the answer to at this point. Thank you! This is one of those weird things that I haven’t been able to google.

What you want to do is best accomplished through polymorphism. There’s a decent explanation and example in this MSDN article.

In your case you would Make a base class (or script in UnityScript lingo) called, e.g, stage and declare the methods common to all stages as abstract. Then implement those methods in your stage-specific classes (or scripts). I would offer a code example but I have no idea how to do it in UnityScript.

You can do this with either polyporphism and inheritance, or Interfaces please see my code here below;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Person> persons = new List<Person>() { new Employee(36, "claus", "dawnson", 12345678), new Customer("ge2tt64mg", "martin", "smith", 78901234) };
            persons.OrderBy(p => p.lastname).ThenBy(p => p.firstname);
            foreach (Person p in persons)
            {
                Console.WriteLine(p.ToString());
            }
            Console.ReadKey();
        }
    }
 

    public abstract class Person
    {
        public string firstname { get; protected set; }
        public string lastname { get; protected set; }
        public int phonenumber { get; protected set; }
 
        public Person(string _firstname, string _lastname, int _phonenumber)
        {
            firstname = _firstname;
            lastname = _lastname;
            phonenumber = _phonenumber;
        }
 
        public abstract override string ToString();
        public virtual string GetCustomerID()
        {
            return null;
        }
    }
 
    public class Customer : Person
    {
        public string customerID { get; protected set; }
 
        public Customer(string _customerID, string _firstname, string _lastname, int _phonenumber)
            : base(_firstname, _lastname, _phonenumber)
        {
            customerID = _customerID;
        }
 
        public override string ToString()
        {
            return firstname + " " + lastname + " " + phonenumber + " " + customerID;
        }
 
        public override string GetCustomerID()
        {
            return customerID;
        }
    }
 
    public class Employee : Person
    {
        public int worktime { get; protected set; }
 
        public Employee(int _worktime, string _firstname, string _lastname, int _phonenumber)
            : base(_firstname, _lastname, _phonenumber)
        {
            worktime = _worktime;
        }
 
        public override string ToString()
        {
            return firstname + " " + lastname + " " + phonenumber + " " + worktime;
        }
    }
}

This is a very basic C# program you can compile with most compilers. as you can see Person is in this case our “superclass” or “baseclass” or “parrentclass”. Employee inherit from Person which mean that you can have a instance of “Person” which really is an Employee or Customer like this:

Person customerp = new Customer(someid, fname, lname, pnum);
Person employeep = new Employee(worktime, fname, lname, pnum);

Now here come the magic of polymorpism; you can see that Person implements an virtual method GetCustomerID() which is overridden in the child class Customer. this makes is posible to do this:

customerp.GetCustomerID();
employeep.GetCustomerID();

now take a guess what would be sent back, on both of them!

ok answers: customerp.GetCustomerID(); will return whatever is in the CustomerID where employeep.GetCustomerID(); will return null since Employee does not implement the “GetCustomerID()” method.

As you can see Person also have an abstract method ToString() which is overridden and always MUST be overridden in the child classes that inherit from the parent class. again you are able to call the tostring method on a person and get the result of the child class. My advice would be to try play around with just alittle to understand it and then implement it as you want to in your game.

Best of luck :slight_smile:

If you don’t really care about performance or strong typing, you can also use “SendMessage” like this:

gameObject.SendMessage("DoSomething");

That will call the method “DoSomething()” on all components of the gameObject that have that method.