Extending MonoBehavior and GameObject?

Hello, I am fairly new to Unity and I came across a situation where I would have liked to make a class that extends GameObject, and trying to come up with a different solution, I stumbled upon quite a few interrogations.

The situation was that I wanted to make tiles on a surface, where each tile is a GameObject and each tile will know if its index on the board (i,j) and if its accessible (boolean).

My initial instinct was to extend a GameObject. I found out quickly enough that I can’t. I assume this is to maintain some consistency in the unity architecture and make sure everything is only extensible by components. Is there more to it than that?

I then started making a class with a GameObject member, which I could render. I needed the Update function (so to not have to run through all my tiles one by one and call render on each one), so I extended from MonoBehaviour.

After reading through the doc a bit, I found out that a MonoBehaviour object needs a GameObject attached to it, and that each script is in fact a MonoBehavior extension. This made my new class doubly redundant, so I ended up simply adding the indices and boolean to my script, attaching it to a GameObject and making it a prefab.

Now, to create my tile and assign its index, I do something like this:

var newTile : GameObject = Instantiate(tilePrefab, transform.position, transform.rotation) as GameObject;
var t : Tile = newTile.GetComponent(Tile); //Tile is the script mentioned above
t.i = i;
t.j = j;
t.occupied = true;

This seems kind of unnatural to me. First, to extend a GameObject I need to actually add components to it. But to be safe, I should probably verify that the new GameObject instantiated has a component called of type Tile. This makes for a call to verify, a call to get the script, and three calls to the script to initialize its values, instad of being able to do something like

var newTile : Tile = new Tile(i,j);

is a Tile extended a GameObject. Secondly, this means that if there is no Tile component attached to the newly created GameObject, the game will shoot out an error at runtime instead of at compilation time.

So that’s it. The question is: Is there an elegant solution to this that I am unaware of, or is this the Unity way of doing things?

Secondary question: If all scripts are in fact Objects derived from MonoBehaviour, is there a situation where I would want to explicitly create a class that extends MonoBehaviour?

I hope that this was all clear, I will keep an eye on this question and edit whatever is unclear.

I would be more inclined to write a single script that contained an array representing the board, and handled instantiating the objects as necessary. I doubt you need the Update function, unless I’m misunderstanding what you mean by “so to not have to run through all my tiles one by one and call render on each one”, since Unity handles the rendering anyway. Adding components to GameObjects as you describe is “the Unity way”, though I use that technique for objects that should be more or less independent, rather than tiles making up a game board (in a sense they are all part of a single object). But that’s a matter of preference.

If using the GetComponent method, though, there are ways to streamline that. Casting when using Instantiate is unnecessary in Unityscript, for one (it automatically returns the type of the prefab being instantiated). It seems unnecessary to create a variable to use with Instantiate if all you’re using it for is GetComponent, so those two lines can be combined. You can write a function in the Tile script that initializes the i, j, and occupied variables. So:

var tile = Instantiate (tilePrefab, transform.position, transform.rotation).GetComponent (Tile);
if (tile) {
    tile.Initialize (i, j);
}

As for explicitly extending MonoBehaviour, that’s only necessary when using C#. In Unity 3, using getters/setters in Unityscript required an explicit class, but that’s fixed in Unity 4, so there’s no reason I can think of to explicitly extend MonoBehaviour when using Unityscript now.