- Home /
Using "Vector3.MoveTowards" to translate an object to mouse click
I'm looking to translate an object to a mouse click, but do so so the object actually travels to the click instead of "snapping" to the mouse click.
I am trying to use the function "Vector3.MoveTowards()" to accomplish this, but to no avail. What am I doing wrong? (Code Below)
Other info:
Game world is a birds-eye camera, Cube with dimensions (200,2,200) and a Sphere called "Player" with (10,10,10) dimensions
The Player Object has a RigidBody attached
I have tried variations of ordering my MoveTowards function, and also tried Lerp and Slerp
using UnityEngine; using System.Collections; public class MoveToClick : MonoBehaviour { GameObject player; RaycastHit hit; Vector3 playerPos = new Vector3 (0,5,0); float speed; // Use this for initialization void Start () { player = GameObject.Find("Player"); player.transform.position = playerPos; speed = 100.0f; hit = new RaycastHit(); //speed = speed * Time.deltaTime; } //Update is called once per frame void Update () { if (Input.GetKeyDown(KeyCode.Mouse0)) { if (Input.GetMouseButtonDown(0)) { movePlayer(); } } } void movePlayer(){ Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out hit, 1000.0f)) { print(playerPos + " " + hit.point + " " + speed); transform.position = Vector3.MoveTowards(hit.point, playerPos, speed); } } }
Note "$$anonymous$$oveTowards" as well as all Lerp variants don't do an animation, they return a single value, once. To move the object each frame a bit, you'd have to do something every frame. Unless you are applying a force to a Rigidbody. Also, maybe this will help: Rigidbody.$$anonymous$$ovePosition
Answer by Lovrenc · Jan 12, 2013 at 01:01 AM
2 mistakes here:
You are only moving your character when you press your key. How can you get animation then? When you press youre key, you should store the value he has to walk to (Vector3). You have to animate it every frame (or until he reaches that spot).
Vector3.MoveTowards has 3 parameters. StartPosition, EndPosition, and a float, that says where you should be between those 2 points.
If last parameter is 0: You will be in start position; If last parameter is .5f: You will be in the middle of 2 positions; If last parameter is 1: You will be on end position;
using UnityEngine;
using System.Collections;
public class MoveToClick : MonoBehaviour {
GameObject player;
RaycastHit hit;
Vector3 playerPos = new Vector3 (0,5,0);
float speed;
Vector3 previousPosition;
Vector3 targetPosition;
float lerpMoving;
// Use this for initialization
void Start () {
player = GameObject.Find("Player");
player.transform.position = playerPos;
speed = 100.0f;
hit = new RaycastHit();
//speed = speed * Time.deltaTime;
}
//Update is called once per frame
void Update () {
if (Input.GetKeyDown(KeyCode.Mouse0)) {
if (Input.GetMouseButtonDown(0)) {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit, 1000.0f)) {
previousPosition = transform.position;
targetPosition = hit.point;
lerpMoving = 0;
}
}
}
if(lerpMoving < 1)
movePlayer();
}
void movePlayer(){
lerpMoving += Time.deltaTime;
transform.position = Vector3.MoveTowards(previousPosition, targetPosition, speed * lerpMoving);
}
}
}
Your update works, and for that I thank you.
Could you expand a little bit on you first talking point. Do you mean animating in the conventional sense, or do you mean something else when you say it?
I ment this: Your movement code has to execute every frame (if ofcourse player is to move that is). How you set it up, you only were calling movement command when you held your mouse button down (because you had the code inside is$$anonymous$$ouseDown if statement bracket).
Naturally every frame (not totally true but lets keep it like that) your code has to calculate new position for the gameObject to put it there.
Look at his code. When you press the mouse button, lerp$$anonymous$$oving
is set to 0. Then further down, still in Update()
and therefore called every frame, he calls movePlayer(), which changes transform.position, each frame a little further. That's what is meant by "animating". Every frame you add some small delta to a position or rotation, and in the end, with enough fps, this looks like movement.
Ah, I understand you both now. $$anonymous$$akes things a little clearer.
Once again, thank you both for your help
I know this is an old post, but shouldn't you incorporate the speed in the lerp$$anonymous$$oving float variable ? I mean, say lerp$$anonymous$$oving is 0.01, then in your movePlayer function, the 3rd parameter of the $$anonymous$$oveTowards, would be 1, as 0.01 * 100 (speed) = 1; But you'll keep calling your movePlayer() as lerp$$anonymous$$oving is still below 1, but the object has already reached it's final position, so there's no point in doing the check again ? So a way around this would be : lerp$$anonymous$$oving += (speed*Time.deltaTime) ?