Building a real-time strategy game in Unity 4.1 using C# scripting

<
>

Part 4: World Objects

The time has now come for us to lay the foundations for interacting with objects in our world. There are 3 main types of objects with which we will want Players to interact with in various ways. These can broadly be classified as Units, Buildings, and Resources. Units will be running round collecting things and / or attacking things. Buildings will form the majority of the bases in the world. And Resources exist to be collected so that a Player build up their base and army, enabling them to take over the world.

Each of these objects is distinct in their own way. However, all 3 of these types of objects will share a number of things in common.

With this in mind, we will make careful use of inheritance to cut down on the amount of code we need to think about and maintain.

To get us started, let's create a new folder in our Assets directory called WorldObject. There should now be 3 folders sitting in this directory - Player, RTS, and the newly created WorldObject. Inside the WorldObject folder create another 3 folders called Building, Resource, and Unit. We will not be doing anything in these today, but we will make use of them later in the project. Finally, add a new C# script into the WorldObject folder and call it WorldObject.cs. This script is where we shall define our basic world object and it's core behaviour.

First up let's create the following public variables at the top of our class. Remember, by declaring them public we can assign values to them directly within Unity. This is useful for testing and for easily changing details if we need to. We can, if we like, set a value here as a default value to be used.

				public string objectName;
				public Texture2D buildImage;
				public int cost, sellValue, hitPoints, maxHitPoints;

We will not use any of these variables right now, but it is useful to set them up anyway. Also, some of these details will not make as much sense for a Resource, but those details can simply be ignored at run time. And it may be that we actually want to implement a resource that the user must construct first anyway (which would actually blur the lines between building and resource even further).

Next we shall add a couple of protected variables. Since these are protected, rather than private, they can be accessed by any subclasses of WorldObject. However, since they are not public they are not able to be reached by any random external classes (or edited from within Unity).

				protected Player player;
				protected string[] actions = {};
				protected bool currentlySelected = false;

As with our HUD last time, we want to be able to access the Player that might own a given WorldObject. We also make use of a boolean variable to determine whether someone has currently selected this object. And finally, we will allow an object to define a list of actions that it can perform. Exactly what the results of those actions are will be left up to a subclass to determine. This could be, for example, building other objects, repairing objects, researching upgrades - it all depends on what the object is and what it is able to do within the game.

In order to make sure that a subclass can have it's own implementation of Unity methods, while still being able to run the default implementations of those methods, we need to declare them protected virtual. This is one of those 'This is how C# / Unity require things to be' situations. Make sure the following methods are declared after your variables, replacing any code that Unity provided for you.

				protected virtual void Awake() {

				}

				protected virtual void Start () {
				    player = transform.root.GetComponentInChildren< Player >();
				}

				protected virtual void Update () {

				}

				protected virtual void OnGUI() {
				}

The difference between Awake() and Start() is that Start() is only called if the script instance is enabled. This allows you to delay any initialization code, until it is really needed. Awake() is always called before any Start() functions. This allows you to order initialization of scripts. Notice that once again we are getting the reference to the Player very early on.

There are two other things that we wish to define now for our WorldObject. The first is the ability to tell it whether it has been selected or not. We will do this by adding the method SetSelection() as outlined below.

				public void SetSelection(bool selected) {
				    currentlySelected = selected;
				}

For now all this does is change the selection state to whatever was specified. The other thing to add is a pair of methods to look after actions. We will provide an accessor for all the methods that we have defined as well as a virtual method for performing an action. By declaring a method virtual we are telling C# that any subclass can provide an implementation for that method. The methods should look as below.

				public string[] GetActions() {
				    return actions;
				}

				public virtual void PerformAction(string actionToPerform) {
				    //it is up to children with specific actions to determine what to do with each of those actions
				}

And that wraps up the framework for our WorldObject. We have nothing to add this to just yet, but we will get there in the next couple of parts as we begin to define Buildings and Units. A shorter entry this time, but it provides us a good platform to build upon. Once again, the complete code for this is up on github under Part 4. In the next part we will build on this foundation and provide the basic implementation for Buildings as well as adding the ability to select objects in our world.

<
>