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:

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:

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!

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).

21 thoughts on “Move Player to Click/Touch Position

    • You can simply set the FlipX property on the sprite to change the direction it faces. Of course you’d need a sprite that faces in one direction instead of the sprite included in the blog post.

      Something like:

      var spr = GetComponent();
      spr.FlipX = true;

      FlipX = false leaves the sprite in its default direction, FlipX = true flips the sprite to face the other direction.

  1. Hello! you talk about making the target sprite fade away after a short time…
    How would you go about to do this? Ive been trying for a while tonight and the sprite disapprear once and never come back…

    Thanks for your help!

    Julien

    • What you need to do is change the sprite’s ‘alpha’ property (transparency) from 1 (fully visible) to 0 (fully transparent) over a period of time (e.g. 0.3 seconds).

      You will want to create a co-routine (which is a method that can do something over a period of time rather than all at once), and change the sprite’s alpha gradually over time.

      You set the alpha value like this (0 = transparent, 1 = solid):

      spriteObject.color = new Color(1f, 1f, 1f, alphaValue);

      So you could have a for loop that adjusts the value over time, set the alpha to 1 when the player clicks, then call the co-routine to fade it out.

      This will get you started: https://answers.unity.com/questions/595001/fading-sprites-alpha-via-coroutine.html

      Also, there is a free Unity asset called iTween, which can do all this for you. It's a good idea to learn how it works, but iTween will let you do it with a single line of code.

      • Very interesting! i will check all of this out tonight and keep you posted! ..

        sadly the code you pasted in your message is showing badly.

        this is what I see:

        [code]]czo1NzpcIiBzcHJpdGVPYmplY3QuY29sb3IgPSBuZXcgQ29sb3IoMWYsIDFmLCAxZiwgYWxwaGFWYWx1ZSk7IFwiO3tbJiomXX0=[[/code]

        Thanks for your help!

      • Ok! I managed to make a working coroutine script that fades my target image! .. the question now is .. How do I start the coroutine script applyed to my target icon from the script that make my player move?

        • I’ve fixed the messed up pasted code (I think).

          To call the co-routine from another script, make it public (so the other script can access it), then do something like this:

          otherScript.StartCoroutine("FadeSprite");

          You'll need a reference to the other script, which you can do in several ways. Have a look here: https://answers.unity.com/questions/7555/how-do-i-call-a-function-in-another-gameobjects-sc.html

  2. Hi Damien! I could finally manage to make my target move and fade! .. I made this code:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class FadeMoveIcon : MonoBehaviour
    {
    SpriteRenderer rend;

    // Use this for initialization
    void Start ()
    {
    rend = GetComponent ();
    }

    IEnumerator FadeOut()
    {
    for (float f = 1f; f >= -0.05f; f -= 0.05f)
    {
    Color c = rend.material.color;
    c.a = f;
    rend.material.color = c;
    yield return new WaitForSeconds (0.05f);
    }
    }
    public void startFading()
    {
    StartCoroutine (“FadeOut”);
    }
    }
    The problem is when I click multiple times to move my player, the target image flickers weirdly while fading out. Do you see what could cause that problem in my code? Do you know of a better way in this case to fade my image and restart the coroutine completly when clicking a new time… everytime.. if you know what I mean..

    Thanks for your help!

    • As you imply, the problem looks to be that the coroutine will run multiple times in parallel if you click while it is already running, so multiple coroutines will be trying to change the colour at the same time, and it will flicker.

      What you can do is stop the coroutine if it is already running, then start a new one:

      StopCoroutine(“FadeOut”); // put this before the StartCoroutine() to stop any existing coroutines

  3. Thanks for posting this tutorial! Would it be possible to make it so your clicks add a force to the sprite in the direction of your mouse cursor instead of moving the sprite directly to that location?

    • It should be pretty easy to achieve that. You’d have to first make the ‘player’ physics enabled (add a rigidbody/rigidbody2d), then replace the code to move the sprite with something to alter the player’s velocity. I think you could get the direction by subtracting the player’s position from the mouse click position, then apply that as the velocity of the rigidbody (you can experiment with multiplying it by a speed to move faster or slower). You could also try ‘AddForce’ to push the player instead of directly setting the velocity.

  4. thank you very much. it is working!
    i have job interview, and use this code to make the program. and thank you very much for sharing! it is worked!!!!

    Good JOB buddy, keep going!!!

    By Randy

  5. Thank you it is working!
    I have been searching everywhere, many error, but it is working!
    Thank you, you save my job interview!

    GOOD JOB! Keep going and sharing!!!
    Many people helped by you!

    by
    Randy

  6. Hi Damien
    I hope you can help me out as I’ve been struggling on this problem for a long time now,

    I have a walking animation, and when I click the screen he walks there, but when he reaches the position of clicked, he’s still stuck in the walk animation loop ( i don’t use the unity animator but imported spines)

    so I really need help on when the object has reached the position of clicked destination to then play stand animation

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

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

    • I think you have the animation in the wrong places. Where you have ‘Standing()’ is where the character needs to move, so you should put Walking() there. Add an else to the ‘if ((Vector2)transform.position != targetPos)’ so it’s something like this:

      if ((Vector2)transform.position != targetPos) // not currently at target position, so need to walk towards it
      {
      transform.position = Vector2.MoveTowards(transform.position, targetPos, speed * Time.deltaTime);
      Standing();
      }
      else
      {
      // player is at the target position, so should play the standing animation
      Standing();
      }

      • I really can’t thank you enough I almost started crying with joy!! I have been trying to get this to work for such a long time and have made some seriously long-winded complex scripts. I do have one final problem. because it’s in the update per frame, the stand animation is not looping but frozen

        I really really appreciate your help today and helping me pass this locked door.

        void Update()
        {
        if (Input.GetMouseButtonDown(0))
        {
        SkelAnim.state.SetAnimation(0, walk, true);
        target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        }
        if ((Vector2)transform.position != target)
        {
        SkelAnim.state.SetAnimation(0, walk, true);
        transform.position = Vector2.MoveTowards(transform.position,
        target, playerSpeed * Time.deltaTime);

        }
        else
        {
        SkelAnim.state.SetAnimation(0, stand, true);
        }
        }
        }

        • I got it working mate thanks for all your help, for anybody else in future who has discovered this post and is trying to LEARN TO CODE

          else if (SkelAnim.state.GetCurrent(0).ToString() != “stand”)
          {
          SkelAnim.state.SetAnimation(0, stand, true);
          }
          }

  7. Thanks for nice help,How can we draw a line from player’s position to the target position and player will follow that line,and if there is hurdle line should be around that hurdle not striking with that hurdle,

Leave a Reply to Damien Cancel reply