Creating an RTS in Unity: Part V

Update: This can now also be found at stormtek.geek.nz/rts_tutorial/part5.php, where the entire tutorial is now being hosted.

Now that we have created a framework for WorldObjects, let’s begin an implementation for a Building. We will create the basic framework for a building, attach this to a simple object, and then enable selection of that building – along with a basic display in the HUD of what has been selected.

Basic Building

First off, let’s create a new script in the Building folder that we created last time, we will call it Building.cs. The first thing we need to do is to make sure that our building inherits from WorldObject. To do so, change the class definition to the following.

public class Building : WorldObject {

This is the C# way of saying that we inherit from another class. Once we have done this, we need to override the Unity methods that we declared virtual in our WorldObject. For now we will simply get them to call their base implementation. You should have the following inside your Building class now.

protected override void Awake() {
	base.Awake();
}

protected override void Start () {
	base.Start();
}

protected override void Update () {
	base.Update();
}

protected override void OnGUI() {
	base.OnGUI();
}

This forms the most basic framework that we need for our building, but we will be adding to this over time. Now create a new empty object in Unity and rename it Building. (GameObject->Create Empty) To this new object, let us add two cubes – we will call them Floor1 and Floor2. (GameObject->Create Other->Cube) Make sure that the Transform properties for the Building object have the following settings: Position = (0,0,0), Rotation = (0,0,0), Scale = (1,1,1). For Floor1 set them to: Position = (0,2,0), Rotation = (0,0,0), Scale = (10,4,10). And for Floor2 set them to: Position = (0,6,0), Rotation = (0,0,0), Scale = (5,4,5). You will notice that the cube which we created in the first part is now in the way. To move it, set the Position property for it’s Transform to (0,2,-20). This moves the cube 20 units down the z-axis and out of the way of our new building. The final thing we need to do with our building is to attach the Building script that we created just before to our Building object.

Building Selection

The first thing we need to add when we want to look at implementing selection of world objects is a method for handling that input. You will recall that we attached a script called UserInput to our player in an earlier part. We will make use of this script to handle responding to mouse input for our player, beyond simple control of our camera. In the Update method, after the call to CameraRotation(), add a call to MouseActivity(). Now create a private method called MouseActivity and add the following implementation to it.

private void MouseActivity() {
	if(Input.GetMouseButtonDown(0)) LeftMouseClick();
	else if(Input.GetMouseButtonDown(1)) RightMouseClick();
}

This method is simply detecting whether the left or right mouse button has been clicked and is passing on handling of that event to the appropriate method. Now we must implement both of these methods within UserInput, to complete our handling of mouse input from the user. We will use the left mouse button for selecting objects and performing actions for a selected object and then we will use the right mouse button for cancelling the selection of an object. Let us look at the left mouse click first. Add the following code into a private method LeftMouseClick.

private void LeftMouseClick() {
	if(player.hud.MouseInBounds()) {
		GameObject hitObject = FindHitObject();
		Vector3 hitPoint = FindHitPoint();
		if(hitObject && hitPoint != ResourceManager.InvalidPosition) {
			if(player.SelectedObject) player.SelectedObject.MouseClick(hitObject, hitPoint, player);
			else if(hitObject.name!="Ground") {
				WorldObject worldObject = hitObject.transform.root.GetComponent< WorldObject >();
				if(worldObject) {
					//we already know the player has no selected object
					player.SelectedObject = worldObject;
					worldObject.SetSelection(true);
				}
			}
		}
	}
}

At the moment, most of this code will fail since we have not implemented the appropriate properties and methods. But before we get onto that, I want to spend just a moment going over the logic of this piece of code. The first thing to take note of here is that we only wish to handle mouse clicks which happen inside our playing area. If the mouse is somewhere inside our HUD we will let the HUD handle mouse input. Now, since our left click is being used for selection and action, we need to determine what the user hit. There are two distinct possibilities here – either the user clicked on a world object, or they clicked on the ground (at the moment this is simply a flat plane, but this could potentially become actual terrain with hills, etc.) somewhere. We will create a pair of helper methods to determine what the point in the world was that the player clicked on, and which object (if any) they clicked on. By adding the field InvalidPosition to our ResourceManager we are able to handle clicks in unidentifiable places (for example the sky), which can then be ignored. So if we have a valid object that we clicked on (even if it was only the ground), and the point which we clicked on was valid, we want to do something with that mouse click. It is important to note that what happens with the mouse click will change depending on whether or not there is already an object selected. If there is, we need to let that object handle the mouse click. If not, we need to determine whether an object needs to be selected or not. If the object clicked on was not the ground, and it was a world object, we can select it. If not we can ignore the mouse click altogether. It turns out that this small piece of code is actually handling a lot of different scenarios.

Now it is time to add in all the pieces of code that this method requires. The first check we have here is to see whether the mouse is inside the playing area or not. Add a reference to the HUD for a player to the top of the Player class like so

public HUD hud;

and then initialize it in the Start method for the Player.

hud = GetComponentInChildren< HUD >();

This finds the HUD script that we added to our player. Now we need to add the method to the HUD which actually determines whether the mouse is inside the playing area or not. The following code should do it.

public bool MouseInBounds() {
	//Screen coordinates start in the lower-left corner of the screen
	//not the top-left of the screen like the drawing coordinates do
	Vector3 mousePos = Input.mousePosition;
	bool insideWidth = mousePos.x >= 0 && mousePos.x <= Screen.width - ORDERS_BAR_WIDTH;  	bool insideHeight = mousePos.y >= 0 && mousePos.y <= Screen.height - RESOURCE_BAR_HEIGHT;
	return insideWidth && insideHeight;
}

Note here that Unity is a little weird in that the origin for the screen coordinates is in a different place than the origin for the drawing coordinates is. This is an annoyance, but it can be worked around as long as you are aware of it. This method simply finds the current position of the mouse and determines whether it is inside the playing area or if it is over part of the HUD.

Let us now find out which object, if any, the user clicked on by adding the following method to UserInput.

private GameObject FindHitObject() {
	Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
	RaycastHit hit;
	if(Physics.Raycast(ray, out hit)) return hit.collider.gameObject;
	return null;
}

By default this method will return a null object. To find which object was hit we make use of some Unity methods. The ray is a line running from the point on screen where the user clicked into the world, from the perspective of our main camera (the only camera that we have in our world). Physics.Raycast() then traces this line and finds the first object in the world to be hit. If it finds it this is stored in the variable hit, if not the method call returns false. If we do find an object we return the parent of that object. Slightly complicated, but all of the dirty work is actually being handled by Unity for us, which is nice.

We do a very similar thing to find the point in the world on which the player clicked, as can be seen in the following method (which also needs to be added to UserInput).

private Vector3 FindHitPoint() {
	Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
	RaycastHit hit;
	if(Physics.Raycast(ray, out hit)) return hit.point;
	return ResourceManager.InvalidPosition;
}

There are a couple of places now where we are referencing the value InvalidPosition, so let’s add it to our ResourceManager now with the following code.

private static Vector3 invalidPosition = new Vector3(-99999, -99999, -99999);
public static Vector3 InvalidPosition { get { return invalidPosition; } }

By creating the private variable invalidPosition we are saving ourselves from needing to create a new Vector3 every time InvalidPosition is referenced. Remember, every little bit can add up very quickly to lots of unnecessary work which in turn slows our game down. Now it is time to add a reference to Player for the current selection. Add the following to the public variables to the top of our Player class.

public WorldObject SelectedObject { get; set; }

This is CSharp’s way of creating a hidden private variable exposed through a getter and setter method. Our player is now ready to store a world object that it has selected. With this in place, let us now create the MouseClick method for WorldObject.

public virtual void MouseClick(GameObject hitObject, Vector3 hitPoint, Player controller) {
	//only handle input if currently selected
	if(currentlySelected && hitObject && hitObject.name != "Ground") {
		WorldObject worldObject = hitObject.transform.root.GetComponent< WorldObject >();
		//clicked on another selectable object
		if(worldObject) ChangeSelection(worldObject, controller);
	}
}

This method will define the basic handling for a mouse click for a world object. Any special details are left up to any subclasses to define. You will note that we are passing in a player to this method. That player is the one who is controlling input at the moment. It may not be the player which owns this world object, which is why we need a reference to them. The basic idea here is to determine whether the object clicked on was a world object and to select it. For now this will allow us to change what has been selected, although that will not be obvious until next time (although feel free to play around with adding more buildings and trying it out). Later on we will add some more logic in here, but for now it is time to implement the ChangeSelection method that is being called here.

private void ChangeSelection(WorldObject worldObject, Player controller) {
	//this should be called by the following line, but there is an outside chance it will not
	SetSelection(false);
	if(controller.SelectedObject) controller.SelectedObject.SetSelection(false);
	controller.SelectedObject = worldObject;
	worldObject.SetSelection(true);
}

We need to make sure that the object the controlling player has selected is deselected (which should be this object, but there is a chance that it might not be). Once we have done so we can set the selection for the controlling player to be the object which was clicked on, which we then make sure is told that it has been selected.

Now that we have code in place to select a world object, it would be good to add some basic visual feedback to the user. For now we will make this as simple as displaying the name of the selected object at the top of the orders bar in our HUD. To do so, add the following code to our HUD script inside the DrawOrdersBar method. This should go between the call to GUI.Box() and GUI.EndGroup().

string selectionName = "";
if(player.SelectedObject) {
	selectionName = player.SelectedObject.objectName;
}
if(!selectionName.Equals("")) {
	GUI.Label(new Rect(0,10,ORDERS_BAR_WIDTH,SELECTION_NAME_HEIGHT), selectionName);
}

If the player has nothing selected then we do not wish to draw anything. However, if they do we wish to get the name of that object and draw that in a label at the top of our orders bar. You will need to create the constant variable for selection height at the top of HUD as follows.

private const int SELECTION_NAME_HEIGHT = 15;

The other thing you need to do is to define the settings for a Label under the skin OrdersSkin. This will allow you to set up whatever styling you want. I have used the settings shown in the screenshot below to get some nicely centred text.

Settings for Label

Settings for Label

There is just one more thing to do before running your code to test the new building selection. As you will have noticed, we are going to display the name of the building that we select. But before we can do this, we actually need to set the name for our building. To do so, click on the Building object that you created in Unity back near the start of this post. In the inspector you will see a number of variables for which you can set values (the public variables declared at the top of our Building script and our WorldObject script). Enter a value, any value, in the Object name field. Now when you run the project in Unity and select your building this name should appear at the top of your orders bar area.

The last thing left to do this week is to implement our right click method for handling input from the mouse. Remember, we are going to use this to cancel whatever selection the player currently has. The snippet of code below should do just nicely (it belongs inside UserInput remember?).

private void RightMouseClick() {
	if(player.hud.MouseInBounds() && !Input.GetKey(KeyCode.LeftAlt) && player.SelectedObject) {
		player.SelectedObject.SetSelection(false);
		player.SelectedObject = null;
	}
}

Once again we make sure that the mouse is inside the playing area. Also, remember that if we are holding down the left alt button and clicking with the right mouse button we are rotating our camera? Therefore, if that is the case we need to ignore the right mouse click. If not, we need to deselect whatever the player had selected and then set their selection to null (which indicates nothing selected).

Right, another longer post out of the way, but we have achieved lots today. We are now in a position to define specific types of buildings. And we can now select objects in our world – whether they belong to our player or not – and display the name of the currently selected object to the player. As always, the complete code from the end of this post can be found on github under the commit for Part 5.

Advertisements

43 thoughts on “Creating an RTS in Unity: Part V

  1. anton says:

    i get this error and i am unable to run the code.
    can you please help ?!

    Assets/Player/Player.cs(12,24): error CS0411: The type arguments for method `UnityEngine.Component.GetComponentInChildren()’ cannot be inferred from the usage. Try specifying the type arguments explicitly

    • Neinth says:

      Sometimes you have to check the tutorial with the actual files on his gethub and compare them

      This line “hud = GetComponentInChildren();” is actualy “hud = GetComponentInChildren();” in Player.cs

      • Neinth says:

        didnt work when i copy and pasted

        hud = GetComponentInChildren”HUD”();” except the qoutes are the lesser than and greater than symbols

      • Apologies for that. I try really hard to keep the code identical to what goes on Github. In theory they should both be the same, but occasionally something slips through. Thanks for pointing this one out, I have updated the post now so that it should not be an issue for other people. 🙂

        • Neinth says:

          No problem m8,i appreciate you doing the work for this.

          There are like 3 other instances in this code where the same error happens,I went through and fixed them all without keeping track of them,it’s all because “” is missing at end

          • Neinth says:

            Not sure why it won;t let me use the greater than and less than symbols,bbcode?

            Also wanted to say I did this part,and fixed all the errors,but can’t select the building,not entirely sure why.

  2. anton says:

    thank you it finally worked, now i continue to the next thread, i will be posting any problems that occur, and will be following 🙂
    thanks again mate 🙂

  3. anton says:

    btw an another problem, i have done everything that is written up there in exact.. but when i compile and run. i can’t select anything in the game not even the building , and even when i press on it it doesn’t display anything in the orders bar.
    so basically i understand that i am not selecting. as even i can’t make a selection u know by pressing somewhere and dragging that little box or even by pressing on the object itself.
    any ideas ?

      • Adam says:

        Having the same problem too. Have made sure all code is identical from Github. Have rebuilt the building stack a couple times in case that was it, but no joy. I’ll carry on with part 6 and see if I can continue, and if something there gives a fix.

        • Adam says:

          ah, after starting part 6, it might be because we neglected to Object Name the building “MyBuilding” in the steps above?

  4. Bruce says:

    Hi. Firstly. Thanks for this great tutorial 🙂
    I’m pretty much a beginner with programming using more modern langauges then Pascal, so
    this is helping loads.

    Im having a simular problem as anton.
    I did clear up errors and replecate the binarys on Github exactly except for my notes 🙂
    Im not able to click on anything. well im clicking and nothing is happening.
    The HUD and so on is working like a charm.

    I was just wonderring if there was something i might of done wrong when I created my Building
    object, this seems to be the only step i don’t understand fully. was a suppouse to drag floor1+floor2 into the building object thus creating cubes in it or did i do something completely
    wrong during that step? Do i need to add tags outside of tagging Camera as “MainCamera”?
    Please let me know if you need more info.

    Any help would be greatly appriciated.

    Thanx

    • Bruce says:

      Got it working :S. I found it od that everything up to this point was doing fine so I started a new blank project and just moved files and redid the hierarchy. Working great now 🙂

  5. Bruce says:

    Appologize for the second post. is it necesary to load anny standard Unity assists at all?

    Ment to have that in there 🙂

  6. Tograton says:

    In the void leftMouseClick we have the line:

    WorldObject worldObject = hitObject.transform.root.GetComponent();

    My Unity has a problem with these and say:

    error CS0411: The type arguments for method `UnityEngine.Component.GetComponent()’ cannot be inferred from the usage. Try specifying the type arguments explicitly

    I’ve looked in the GITHubFile there the line is changed to:

    WorldObject worldObject = hitObject.transform.parent.GetComponent();

    This is also not working, but i think its because im just at Part V.
    Any Help for now??

    • You need to specify a type to the call to GetComponent(). In this case, since we are trying to find a WorldObject, this needs to be done like so:

      WorldObject worldObject = hitObject.transform.root.GetComponent< WorldObject >();

      Notice the WorldObject specified between the angle brackets (remove the spaces in your code, although these should not actually matter – I had to put them there to allow this to show properly …)

  7. Jhtti the Runic says:

    elgar, i have a problem with the code up to this point. Every time i go to select the building it dosent respond. I have everything just like it should up to this point and it doesnt want to work. Tips on how to make this work better. Its driving me nuts…

    • Not off the top of my head sorry. I would try printing some things to the console with Debug.Log(“message”). A good place to start might be the methods involved in the click and building selection. Try to track where the code is actually going and take it from there. It is always possible that an if statement somewhere is evaluating differently than expected.

      • Jhtti the Runic says:

        even if the code is 100% the same through musing 1-5? Sounds a bit odd but the code isnt flawed, its not operational…is it the fact im running 4.2+ or the fact that the code is designed for 4.0 and not exactly the same as it should? Just a few investigations worth taking a look at.

        To recap:
        1. i make the floor and the box and set up the primitive camera
        2. I code the basic mouse scroll movement primitive
        3. I code the rest of the setup for handling certian functions verbatim
        4. I code the rest dealing with RTS
        5. I set up the building commands and click functions verbatim
        5-2. I fiscal Cliffs at this point with the building not being clicked

        Is it the fact i need to setup the boxes objects as the hierarchy like: building is the parent of floor 1 and 2 and they go in building as a prefab?

        I know its a lot of questions but its the only thing needed to be nailed down.
        The code works fine just nothings coming up selected.

        • Jhtti the Runic says:

          i have an idea…since my code isnt working right, can you recreate the parts of 1-16 as verbatim, for people to look at the code for those areas, as a recode in your gethub account?

          Be easier to do that than go and try to pick through everything from code save 16.

          • Jhtti the Runic says:

            figured out you already did that, though you had only part 16 available…guess i jumped the gun a little but ill give you a heads up if its just the code vs the new system…

  8. Jhtti the Runic says:

    Found out what it was that was causing the error, the hud object was not in the player object, and for the fact everything was labeled wrong… 😛 its all fine now.

  9. Ji Zhong says:

    My game can run but have a little problem. I cant draw a selectBox, but I can select object by click.(only once)
    Once I already chosed the objects, I choose another object the console show error.

    NullReferenceException: Object reference not set to an instance of an object
    WorldObject.ChangeSelection (.WorldObject worldObject, .Player controller) (at Assets/WorldObject/WorldObject.cs:71)
    WorldObject.MouseClick (UnityEngine.GameObject hitObject, Vector3 hitPoint, .Player controller) (at Assets/WorldObject/WorldObject.cs:64)
    UserInput.LeftMouseClick () (at Assets/Player/UserInput.cs:39)
    UserInput.MouseActivity () (at Assets/Player/UserInput.cs:24)
    UserInput.Update () (at Assets/Player/UserInput.cs:17)

    I dont know where is wrong

    • I would need to see some of your code to be able to help you track things down more sorry. That console error does tell you what line the error is happening on though -> WorldObject.cs line 71, somewhere inside your ChangeSelection() method. It even tells you the methods that were called to get you to that point, to help track down what happened. If your code perfectly matches mine then I cannot see how it could break, since there are checks in place to make sure that you do not get a NullReferenceException. My guess would be that somehow either the Player object being passed into ChangeSelection() or Player.SelectedObject is null, but as I said before I cannot tell that from here without seeing any code.

  10. Christian says:

    No errors for me but when I click the building, the name I gave it shows up in the HUD but the bottom third of the text is cut off, any idea why?

      • Christian says:

        Fixed it by changing the int selection name height from 15 to 30 like shown below, thanks for the quick reply and great tutorial
        private const int SELECTION_NAME_HEIGHT = 30;

  11. Hi again, thanks heaps for your tutorial, it’s saving me from my IST project. My issue now is when i go into play mode I cannot select the building and make it show up in the Orders Bar. Can you see what I’ve done wrong?
    The Building object contains only the building script, as well as floor1 and floor2 as children.
    Here is my HUD.cs:

    using UnityEngine;
    using System.Collections;
    using RTS;

    public class HUD : MonoBehaviour {

    public GUISkin resourceSkin, ordersSkin;
    private const int ORDERS_BAR_WIDTH = 150, RESOURCE_BAR_HEIGHT = 40;
    private Player player;
    private const int SELECTION_NAME_HEIGHT = 15;

    // Use this for initialization
    void Start () {
    player = transform.root.GetComponent();

    }

    // Update is called once per frame
    void OnGUI () {
    if(player.human) {
    DrawOrdersBar();
    DrawResourceBar();
    }
    }

    private void DrawOrdersBar() {
    GUI.skin = ordersSkin;
    GUI.BeginGroup(new Rect(Screen.width-ORDERS_BAR_WIDTH,RESOURCE_BAR_HEIGHT,ORDERS_BAR_WIDTH,Screen.height-RESOURCE_BAR_HEIGHT));
    GUI.Box(new Rect(0,0,ORDERS_BAR_WIDTH,Screen.height-RESOURCE_BAR_HEIGHT),””);
    string selectionName = “”;
    if(player.SelectedObject) {
    selectionName = player.SelectedObject.objectName;
    }
    if(!selectionName.Equals(“”)) {
    GUI.Label(new Rect(0,10,ORDERS_BAR_WIDTH,SELECTION_NAME_HEIGHT), selectionName);
    }
    GUI.EndGroup();
    }

    private void DrawResourceBar() {
    GUI.skin = resourceSkin;
    GUI.BeginGroup(new Rect(0,0,Screen.width,RESOURCE_BAR_HEIGHT));
    GUI.Box(new Rect(0,0,Screen.width,RESOURCE_BAR_HEIGHT),””);
    GUI.EndGroup();
    }

    public bool MouseInBounds() {
    //Screen coordinates start in the lower-left corner of the screen
    //not the top-left of the screen like the drawing coordinates do
    Vector3 mousePos = Input.mousePosition;
    bool insideWidth = mousePos.x >= 0 && mousePos.x = 0 && mousePos.y <= Screen.height – RESOURCE_BAR_HEIGHT;
    return insideWidth && insideHeight;
    }
    }

    And my UserInput:

    using UnityEngine;
    using System.Collections;
    using RTS;

    public class UserInput : MonoBehaviour {

    private Player player;

    // Use this for initialization
    void Start () {
    player = transform.root.GetComponent();
    }

    // Update is called once per frame
    void Update () {
    if(player.human) {
    MoveCamera();
    RotateCamera();
    }
    }

    private void MoveCamera() {
    float xpos = Input.mousePosition.x;
    float ypos = Input.mousePosition.y;
    Vector3 movement = new Vector3(0,0,0);

    //horizontal camera movement
    if(xpos >= 0 && xpos < ResourceManager.ScrollWidth) {
    movement.x -= ResourceManager.ScrollSpeed;
    } else if(xpos Screen.width – ResourceManager.ScrollWidth) {
    movement.x += ResourceManager.ScrollSpeed;
    }

    //vertical camera movement
    if(ypos >= 0 && ypos < ResourceManager.ScrollWidth) {
    movement.z -= ResourceManager.ScrollSpeed;
    } else if(ypos Screen.height – ResourceManager.ScrollWidth) {
    movement.z += ResourceManager.ScrollSpeed;
    }

    //make sure movement is in the direction the camera is pointing
    //but ignore the vertical tilt of the camera to get sensible scrolling
    movement = Camera.main.transform.TransformDirection(movement);
    movement.y = 0;

    //away from ground movement
    movement.y -= ResourceManager.ScrollSpeed * Input.GetAxis(“Mouse ScrollWheel”);

    //calculate desired camera position based on received input
    Vector3 origin = Camera.main.transform.position;
    Vector3 destination = origin;
    destination.x += movement.x;
    destination.y += movement.y;
    destination.z += movement.z;

    //limit away from ground movement to be between a minimum and maximum distance
    if(destination.y > ResourceManager.MaxCameraHeight) {
    destination.y = ResourceManager.MaxCameraHeight;
    } else if(destination.y < ResourceManager.MinCameraHeight) {
    destination.y = ResourceManager.MinCameraHeight;
    }

    //if a change in position is detected perform the necessary update
    if(destination != origin) {
    Camera.main.transform.position = Vector3.MoveTowards(origin, destination, Time.deltaTime * ResourceManager.ScrollSpeed);
    }
    }

    private void RotateCamera() {
    Vector3 origin = Camera.main.transform.eulerAngles;
    Vector3 destination = origin;

    //detect rotation amount if ALT is being held and the Right mouse button is down
    if((Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt)) && Input.GetMouseButton(1)) {
    destination.x -= Input.GetAxis("Mouse Y") * ResourceManager.RotateAmount;
    destination.y += Input.GetAxis("Mouse X") * ResourceManager.RotateAmount;
    }

    //if a change in position is detected perform the necessary update
    if(destination != origin) {
    Camera.main.transform.eulerAngles = Vector3.MoveTowards(origin, destination, Time.deltaTime * ResourceManager.RotateSpeed);
    }
    }

    private void MouseActivity() {
    if(Input.GetMouseButtonDown(0)) LeftMouseClick();
    else if(Input.GetMouseButtonDown(1)) RightMouseClick();
    }

    private void LeftMouseClick() {
    if(player.hud.MouseInBounds()) {
    GameObject hitObject = FindHitObject();
    Vector3 hitPoint = FindHitPoint();
    if(hitObject && hitPoint != ResourceManager.InvalidPosition) {
    if(player.SelectedObject) player.SelectedObject.MouseClick(hitObject, hitPoint, player);
    else if(hitObject.name!="Ground") {
    WorldObject worldObject = hitObject.transform.root.GetComponent();
    if(worldObject) {
    //we already know the player has no selected object
    player.SelectedObject = worldObject;
    worldObject.SetSelection(true);
    }
    }
    }
    }
    }
    private GameObject FindHitObject() {
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    RaycastHit hit;
    if(Physics.Raycast(ray, out hit)) return hit.collider.gameObject;
    return null;
    }

    private Vector3 FindHitPoint() {
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    RaycastHit hit;
    if(Physics.Raycast(ray, out hit)) return hit.point;
    return ResourceManager.InvalidPosition;
    }

    private void RightMouseClick() {
    if(player.hud.MouseInBounds() && !Input.GetKey(KeyCode.LeftAlt) && player.SelectedObject) {
    player.SelectedObject.SetSelection(false);
    player.SelectedObject = null;
    }
    }
    }

    Sorry for huge post, but it would help me greatly, thanks!

    • Someone else actually had this same problem … Check your update method in UserInput.cs carefully. I think you will find that you are missing an important method call there. (Hint: you are not actually handling the mouse input at the moment with the code you have there)

  12. I have no idea what I’ve done wrong if anything at all but i can’t seem to select my building. as far as i’m aware i have followed this lesson to the letter and checked my code with that on github. Yet when i click on my building nothing happens.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s