I’m working on a little top down 2D RPG and I’m trying to figure how how to prevent diagonal movement. I’ve succeeded in preventing the character from moving diagonally, but I have a weird issue.
When I’m moving along the x axis and input to move along the y axis, it works as intended and stops moving horizontally and starts moving vertically. However, when I’m moving along the y axis and try to move horizontally, he will just continue moving up. I’m not entirely sure what’s wrong.
The move function is being called in update (though perhaps it should be fixedUpdate). Any thoughts on what I’m doing wrong?
private void movePlayer()
{
float x = Input.GetAxisRaw("Horizontal");
float y = Input.GetAxisRaw("Vertical");
isMoving = false;
Mydir2 = Vector2.zero;
LastDir = dir;
if (y != 0 && !hit)
{
x = 0;
isMoving = true;
dir = new Vector2(x, y);
Mydir2 = dir;
}
else if (x != 0 && !hit)
{
y = 0;
isMoving = true;
dir = new Vector2(x, y);
Mydir2 = dir;
}
myRigidbody.velocity = (Mydir2 * moveSpeed * Time.deltaTime);
myAnimator.SetFloat("moveX", x);
myAnimator.SetFloat("moveY", y);
myAnimator.SetFloat("dirX", dir.x);
myAnimator.SetFloat("dirY", dir.y);
myAnimator.SetBool("isMoving", isMoving);
}
Hm it could be a floating point issue, generally you don’t want to check if a floating point number is exactly equal to another number. Maybe try this:
if (Mathf.abs(y) > 0.01 && !hit)
{
// Move up
}
And do the same for checking the x value. In your case its possible that y is very very close to zero but not actually zero. Computers are a bit error prone with floating point numbers.
Here is what happens, every frame you check first for vertical input, and if there is no vertical input, then you check for horizontal input.
If there is a vertical input, your code will never ever check for horizontal input, because your horizontal is in an “else” statement.
The code below should have the behaviour you want (the results are somehow weird when you hit more than 2 arrows at the same time, but you will never have diagonal movement).
This code isn’t perfect at all (it’s ugly to watch and i’m pretty sure it has a bunch of useless if statements), but it works.
private bool Xfirst, Yfirst;
private Vector2 dir;
public void MovePlayer()
{
float x = Input.GetAxisRaw("Horizontal");
float y = Input.GetAxisRaw("Vertical");
if (y != 0) // If the User is clicking on the vertical axis
{
if (x == 0) // If he's not clicking on the horizontal axis:
{
Xfirst = false;
Yfirst = true; //Then it means he started by moving along the Y axis, and not along the X axis.
dir = Vector2.up * y;
}
if (x != 0) // If he's clicking on the X axis (and on the Y axis at the same time)
{
if (Xfirst)//We check if he clicked first on X.
{
dir = Vector2.up * y; //If he did clicked first on X, then we go for Y , we change direction
}
else
{
dir = Vector2.right * x;//If he did clicked first on Y, then we go for X.
}
}
}
if (x != 0)//This is the same thing, but the other way around.
{
if(y == 0)
{
Xfirst = true;
Yfirst = false;//In fact this way, we set Yfirst to false only when the user releases the Y button.
dir = Vector2.right * x;
}
if (y != 0)
{
if (Yfirst)
{
dir = Vector2.right * x;
}
else if(Xfirst)//Added one more check here. This way, if the player wasn't mooving, but acheive to hit X and Y and the same time, he will go on the Y axis by default.
{
dir = Vector2.up * y;
}
}
}
if(x == 0 && y == 0)
{
dir = Vector2.zero;
}
Debug.Log(dir); //I added this to check the results myself, but you should remove it. Debug.Log eat a lot of performances, a debug.log inside Update() is a bad idea.
}
If you don’t understand the code, just tell me i’ll try to explain better.