I need help with my NES Zelda style player mover script.

I’m trying to make an NES Zelda 1 style player mover script. In that game, you couldn’t move diagonally, and if you had the x and y axes held down together it would move you in the direction most recently pressed.

Basically, you hold down “A” and you move to the left. Without taking your finger off “A”, you press “W” and now you’re moving up (not diagonal, just up). When you take your finger off “W” but leave the other finger on “A”, you move left again.

I wanted to do something like GetButtonDown but for an axis, but that apparently isn’t a thing.

What I tried writing used a bunch of variables and didn’t work. Does not work at all. When holding “A” and “W” down together, the player animation resonates rapidly between walking up and walking left. I understand why it does that, I just can’t figure out the proper way to do this.

I would greatly appreciate any help / advice you can give!

Here’s my bad code:

public class PlayerMover : MonoBehaviour {

	...

	public Vector3 moveDirection = Vector3.zero;

	float moveX;
	float moveY;

	bool xPriority = false;
	bool xInUse = false;
	bool xDown = false;
	bool yInUse = false;
	bool yDown = false;
	bool xMostRecent = false;

	void Update() {

		moveX = Input.GetAxis ("Horizontal");            // sets the left / right
		moveY = Input.GetAxis ("Vertical");              // move direction

		if (Input.GetAxis ("Horizontal") != 0f) {        //
			xDown = true;                            // This tests if
		} else {                                         // the x axis 
			xDown = false;                           // is being pressed
		}						 //

		if (Input.GetAxis ("Vertical") != 0f) {		 //
			yDown = true;				 // This tests if 	
		} else {					 // the y axis
			yDown = false;				 // is being pressed
		}						 //


// This section is the problem. It is the bad code. I have done wrong in its creation.
//
//
		if (xDown && xMostRecent == false) {
			xMostRecent = true;
		} else if (yDown && xMostRecent == true) {
			xMostRecent = false;
		}


		if (xDown == true && xMostRecent == true) {
			xPriority = true;
		} else if (yDown == true && xMostRecent == false) {
			xPriority = false;
		}



		if (xPriority == true) {			// xPriority determines
			moveY = 0f;			// the axis on which
		} else {				// the player is allowed
			moveX = 0f;			// to move	
		}					//

//
//
// Very bad code. It is the mistake. Something important is missing.


		moveDirection = new Vector3(moveX, moveY, 0);
		moveDirection *= speed;	
	}
}

Not really sure why you’d want to artificially restrict the controls like this (what’s wrong with going diagonally?). But fair enough!

You could use Input.GetKey(KeyCode.W) if you want a digital test rather than using an axis.

This code is untested, and you’ll have to implement the IsRightPressed() etc yourself, however you see fit:

enum MoveDirection
{
	None,
	Left,
	Right,
	Up,
	Down
}

MoveDirection moveDirection;

private MoveDirection Movement()
{
	if ( IsRightPressed() )
	{
		return MoveDirection.Right;
	}

	if ( IsLeftPressed() )
	{
		return MoveDirection.Left;
	}

	if ( IsDownPressed() )
	{
		return MoveDirection.Down;
	}

	if ( IsUpPressed() )
	{
		return MoveDirection.Up;
	}

	return MoveDirection.None;
}

private Vector3 ZeldaMovement()
{
	switch ( moveDirection )
	{
		case MoveDirection.None:
		{
			moveDirection = Movement();
			return Vector3.zero;
		}
		break;

		case MoveDirection.Left:
		{
			if ( IsLeftPressed() == false )
			{
				moveDirection = MoveDirection.None;
			}
			else
			{
				return Vector3.left * speed;
			}
		}
		break;

		case MoveDirection.Right:
		{
			if ( IsRightPressed() == false )
			{
				moveDirection = MoveDirection.None;
			}
			else
			{
				return Vector3.right * speed;
			}
		}
		break;

		case MoveDirection.Down:
		{
			if ( IsDownPressed() == false )
			{
				moveDirection = MoveDirection.None;
			}
			else
			{
				return Vector3.down * speed;
			}
		}
		break;

		case MoveDirection.Up:
		{
			if ( IsUpPressed() == false )
			{
				moveDirection = MoveDirection.None;
			}
			else
			{
				return Vector3.up * speed;
			}
		}
		break;
	}
}

Try this

void Update() {

     if (Input.GetKey(KeyCode.A)) 
     { 
         moveX = 1; 
         if (moveY != 0) moveY = 0;
     }   
     else (Input.GetKey(KeyCode.W)) 
     { 
         move = -1; 
         if (moveY != 0) moveY = 0;
     } 
     else {move = 0}


     if (Input.GetKey(KeyCode.W)) 
     { 
         moveY = 1; 
         if (moveX != 0) moveX = 0;
     }  
     else (Input.GetKey(KeyCode.S)) 
     { 
         moveY = -1; 
         if (moveX != 0) moveX = 0;
     } 
     else {move = 0}

     moveDirection = new Vector3(moveX, moveY, 0);
     moveDirection *= speed;  

Hope this help!

All you really need is …

void Update() { 

    moveX = 0;
    moveY = 0;

    if (Input.GetKey(KeyCode.A)) { 
        moveX = -1; // left
        moveY = 0;  // remove to allow diagonal
    } else if(Input.GetKey(KeyCode.D)) { 
        moveX = 1; // right
        moveY = 0; // remove to allow diagonal
    } else if (Input.GetKey(KeyCode.W)) { 
        moveY = 1; // up
        moveX = 0; // remove to allow diagonal
    } else if (Input.GetKey(KeyCode.S)) { 
        moveY = -1; // down
        moveX = 0;  // remove to allow diagonal  	
    } 
        
    moveDirection = new Vector3(moveX, moveY, 0);
    moveDirection *= speed;

    transform.position += moveDirection;
}

Player will be restricted to X or Y movement only.
Cheers!