Move Player to Click/Touch Position

In this tutorial, we’ll make a player character move to a position on the screen where the mouse was clicked or a finger tapped, just like in real-time strategy games and many mobile games.

What We’ll Do

The steps required are:

  1. Create a simple player.
  2. Detect a touch/mouse click position on the screen.
  3. Write a script to move the player to the clicked/tapped position.

The skills you’ll learn in this tutorial are:

  • Detecting mouse/touch position and translating that to a point in the game world.
  • Making an object move towards a point on the screen smoothly.

Getting Started

  1. Create a new Unity project, and choose the 2D settings.

As with all my tutorials, if you’re stuck on the basics, or I mention something you’re not familiar with (or just need more detailed steps), please refer to my Pong tutorial, where everything you need to know about using Unity is shown in detail.

I haven’t included any sprites with this tutorial, so find any sprite/image you want to use for your player. I always recommend Kenney.nl, where you can get lots of free art to use in your projects. In my example, I’m using a rabbit sprite from Kenney’s Animal Pack.

1. Create a Player

The player is going to be simple:

  1. Add an empty GameObject to your scene.
  2. Rename the GameObject to ‘Player’ (select and press F2 to rename).
  3. Add a SpriteRenderer component to the Player.
  4. Add any sprite to your project and assign it to the Player’s SpriteRenderer.

Here’s the Game window as it should look with your player:

image

 

Note
If you can’t see the player (but have definitely added a sprite), make sure the player’s Transform position is [0,0,0], which is the centre of the screen.

That’s all we need for the player.

2. Detect Touch/Mouse Position

Detecting a touch or click position is pretty simple, but has two components. You first need to get the touch position, and then need to convert that to an actual game position so that it matches with your game content.

Create a new C# script called ‘MoveToClickInput’, and replace the entire code in that script with the following:

using UnityEngine;

public class MoveToClickInput : MonoBehaviour
{
    void Update ()
    {
        if(Input.GetMouseButtonDown(0))
        {
            Debug.Log("Mouse button clicked");
        }
    }
}
Input.mousePosition also works for touch input, so we don’t need to write separate code to get a touch. More complex uses of touch can use the specific Unity APIs for handling touch and multi-touch.

The only thing this script does (so far) is check for a mouse click, then print a message to the Unity console window if one is detected.

Input.GetMouseButtonDown checks if the mouse button (button 0 in this case, which is the left mouse button or a touchscreen touch) was pressed down during the current frame. Be careful with these, as it’s easy to get mixed up between GetMouseButtonDown and GetMouseButton (which checks if the mouse button is held down regardless of when it was first pressed down).
Attach that script to the Player object, then test your scene. Click the mouse anywhere in the Game window, and you will see that a message gets printed in the Console window showing you that the code is working.

If you want to try it with a touch device, go ahead and deploy the project and test. It will work the same as with a mouse.

Add a Target

Let’s add a simple target sprite so we can see where the mouse click was (and therefore where the player will move to).

  1. Add a new empty GameObject to the scene.
  2. Rename the new object to ‘Target’.
  3. Add a SpriteRenderer component to Target.
  4. Add a sprite to the Target’s SpriteRenderer component. I used a simple circle sprite and shaded it red and made it semi-transparent.
  5. Make sure the target is centred on [0,0,0] and is visible in the Game window.
If the target is hidden behind the player sprite, change the SpriteRendere’s Order In Layer property so the target has a higher value than the player (which will ensure it is drawn in front of the player sprite).

Here’s my red dot target drawn on top of the player:

image

Now, let’s give the input script a reference to the target, and move the target to the clicked position. Since this script is still very short, here is the entire script with the new code added in:


using UnityEngine;

public class MoveToClickInput : MonoBehaviour
{
    [SerializeField] Transform target;

    void Update ()
    {
        if(Input.GetMouseButtonDown(0))
        {
            Debug.Log("Mouse button clicked");
            target.position = Input.mousePosition;
        }
    }
}

What we’ve added is a Transform variable called ‘target’, and a line of code to move the target transform to the position of a detected click or tap.

To assign the actual Target object to the target variable, go into Unity:

  1. Select the Player GameObject.
  2. Drag-and-drop the Target GameObject into the Target field in the Move to Click script component.

Now run the scene (but beware it won’t work as expected!)…

So you click in the scene, but don’t see the target appear where you click? That’s to be expected because the mouse position reported by Unity is not relative to the game screen. If you look for the target in the Scene window, you’ll find it very far away from where you actually clicked!

Adjust the Mouse Click Position to Game Space

When you get Input.mousePosition, you are getting the position of the mouse in pixel co-ordinates, with [0,0] being the bottom left corner (this is called ‘screen space’). But when you are dealing with transforms in Unity, you are dealing with the ‘world space’, which is the Unity co-ordinate system with [0,0] in the centre, and has a different scale where a single unit represents dozens or hundreds of pixels.

So we need to translate the mouse position from screen space to world space to use it with transforms. Luckily, this is very easy:

var clickedPos = (Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition);

The above code converts the mouse’s screen position to a game world position. The (Vector2) at the front forces the value to be Vector2 (rather than Vector3 default), which ensures the position is at [0] on the Z-axis, since we’re working in 2D.

Replace the script’s Update() method with the following:

void Update ()
{
    if(Input.GetMouseButtonDown(0))
    {
        var clickedPos = (Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition);
        target.position = clickedPos;
    }
}

Now run the scene and the red dot (or whatever you used) should move to where you click the mouse.

3. Move the Player Towards the Click

We now have a player and can detect a mouse click in world space. The next thing we need to do is make the player move to the click. This is not as simple as what wo did for the target object because we want the player to ‘walk’ to the clicked spot.

Let’s go through the code piece-by-piece, and I’ll include the final script at the end.

Firstly, we want to keep track of where the player is heading, so we add a script-level variable that will always remember the player’s current target:

Vector2 targetPos;

We also need to give our player a speed so they move at the rate we want, so a speed variable is required:

float speed = 6f;

When the scene starts, the player doesn’t have a target to move towards, so we set the target position to be equal to the player’s current position in the Start() method:

private void Start()
{
    targetPos = transform.position;
}

We should also rejig the code that gets the mouse position and moves the target so it uses the same targetPos variable that the player will move towards, so that will be changed to the following:

if(Input.GetMouseButtonDown(0))
{
    targetPos = (Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition);
    target.position = targetPos;
}

And after that code, still in the Update() method, we will do the real magic – move the player towards the targetPos:

if((Vector2)transform.position != targetPos)
{
    transform.position = Vector2.MoveTowards(transform.position, targetPos, speed * Time.deltaTime);
}

The above code first checks if the player is already at its target position (if it is, there is no point moving it), then uses Vector2.MoveTowards to (you guessed it) move towards the targetPos from its current position. The third parameter of Vector2.MoveTowards is the movement amount, which is effectively the speed. We multiply our player speed by Time.deltaTime (the time since the last frame) to ensure that the movement amount is kept consistent with the framerate (the framerate is always going to fluctuate a little, so if the player moved the same amount every frame, it would change speed all the time and therefore move very roughly).

Here’s the completed code:

using UnityEngine;
public class MoveToClickInput : MonoBehaviour
{

[SerializeField] Transform target;
float speed = 6f;
Vector2 targetPos;

private void Start()
{
    targetPos = transform.position;
}

void Update ()
{
    if(Input.GetMouseButtonDown(0))
    {
        targetPos = (Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition);
        target.position = targetPos;
    }
    if((Vector2)transform.position != targetPos)
    {
       transform.position = Vector2.MoveTowards(transform.position, targetPos, speed * Time.deltaTime);
    }
}

Try out your scene. You should now have everything working!

rabbit

 

Next Steps

Here are some things you can try adding to improve this little project:

  • Animate the player.
  • Make the target sprite fade away after a short time.
  • Add a particle effect to the target sprite to better indicate a mouse click.
  • Adjust the code so that you can drag your finger around the screen and the player follows (hint: change Input.GetMouseButtonDown to Input.GetMouseButton).

Leave a Reply

Your email address will not be published.