- Home /
How to move 2D character from one place to another by "movement" and not "teleporting"?
Hi everyone
Introduction
I am making some controls for my character who moves only left and right on the x-axis. I posted the code for his movement to left and right. The idea is to have him only move those widths in the game so there's like 5 places he can be on the screen.
public float fieldWidth = 3;
void FixedUpdate(){
if (Input.GetKeyDown(KeyCode.LeftArrow)){
transform.Translate(-fieldWidth, 0,0f, 0,0f);
}
if (Input.GetKeyDown(KeyCode.RightArrow)){
transform.Translate(fieldWidth, 0,0f, 0,0f);
}
}
Problem:
The main problem is that when I used translate in the code then the character "teleports" to those places. It's cool that he can only move 5 places in total with 3.0f each step BUT I wanted to have him "move" those places instead of "teleporting".
After all, I want to add an animation on the character when he moves from one place to another.
Alternative tries:
If I use deltaTime for his movement/velocity then he just moves at that speed and do not stop at one of the 5 places as he does now and is supposed to do.
Goal:
I want him to move 3.0f every time I press Right or Left arrowkey but he should show motion from one place to another instead of teleporting one place to another.
Question:
Could someone help me showing what I'm doing wrong, and what I should do to correct it?
Answer by vptb · May 27, 2014 at 03:14 PM
There's actually several ways to do this, on my opinion you should go with adding a rigidbody2D to you character and move it with velocity.
private Vector3 _destinyPos;
private float _distanceTolerance = 0.1f;
public float fieldWidth = 3;
public float speed = 3;
private void Update(){
if (Input.GetKeyDown(KeyCode.LeftArrow)){
_destinyPos = transform.position - new Vector3(fieldWidth, 0, 0);
}
if (Input.GetKeyDown(KeyCode.RightArrow)){
_destinyPos = transform.position + new Vector3(fieldWidth, 0, 0);
}
}
private void FixedUpdate(){
if (Mathf.Abs(_destinyPos.x - transform.position.x) > _distanceTolerance){
if (_destinyPos.x < transform.position.x) rigidbody2D.velocity = -transform.right * speed;
else rigidbody2D.velocity = transform.right * speed;
}
else rigidbody2D.velocity = Vector2.zero;
}
Receiving Input should always be done on the Update() function. The FixedUpdate() should be used for physics calculations.
Another option is to move him with transform.Translate(). But after some experience recommend using rigidbody.
It worked nicely. Had to move the variables a little up and here and there but it worked wonders. Thanks.
I also added a
if ($$anonymous$$athf.Round(destinyPos.x) == $$anonymous$$athf.Round(targetPosition.x)){}
inside the input if-loop to lock the movements while the character is moving. Otherwise it would be like jumping again in the air while he should only be able to do jump when he's on the ground. (Sorry, the other analogy didn't work right)
Answer by siaran · May 27, 2014 at 01:51 PM
You should determine your player's target position when you press a key, then move him in the direction of your target position (3.0f in some direction from your current position) over time until he has arrived there. Easiest way is probably using Vector2.MoveTowards.
keep in mind that you should make sure that if a key is pressed while the player is moving it the target position is not changed (or changed to a position where you want your player to be able to go depending on what kind of behaviour you want)
It seems that I'll need to insert both the current and the future position into 2 variables and then use those as to not get a new current position all the time.
Thanks, I'll try to look at it when I get home today.
you only need to keep the future position in a variable, and keep a boolean "is$$anonymous$$oving". set to true when you press a key and set to false when the destination is reached, then only accept a new target position when is moving is false.
Thanks, I tried it but I couldn't get it to work right. Dunno why. Still I believe it the logic is right. I went with a modified version of vptb's version.
Interesting, you can't have two right answers...but this one is also right.