# Make Player Move Within 3 Lanes

I’m currently making a little game where there are 3 lanes for the player to move between. They start in the middle lane and can switch between shifting left and right 1 lane over to dodge objects. However, I am having trouble making the movement portion of the game. I tried using game objects to move between on the x axis but had issues with teleporting outside of the map. For now I am just attempting to shift the player over 2 on the x axis.

As of now, my character will move to the left and right lane but cannot return to the middle lane.

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

public class Player_Movement : MonoBehaviour
{
private Rigidbody rb;
private Vector3 inputDelta, shiftLeft = new Vector3 (-2, 0, 0), shiftRight = new Vector3(2, 0, 0);
private float moveSpeed = 100f, jumpHeight = 50f;
private bool jump = false, isGrounded = true, moveLeft = false, moveRight = false;
private int currentLane = 2;

void Start()
{
rb = this.GetComponent<Rigidbody>();
}

void Update()
{
inputDelta.x = Input.GetAxisRaw("Horizontal");

if (inputDelta.x > 0 && currentLane != 3)
{
moveRight = true;
}

if (inputDelta.x < 0 && currentLane != 1)
{
moveLeft = true;
}

if ((Input.GetKeyDown(KeyCode.Space) || Input.GetKeyDown(KeyCode.W)) && isGrounded)
{
jump = true;
}
}

void FixedUpdate()
{
if (moveRight)
{
transform.position = Vector3.MoveTowards(transform.position, transform.position + shiftRight, moveSpeed * Time.deltaTime);
currentLane += 1;
moveRight = false;
}

if (moveLeft)
{
transform.position = Vector3.MoveTowards(transform.position, transform.position + shiftLeft, moveSpeed * Time.deltaTime);
currentLane -= 1;
moveLeft = false;
}
}
}
``````

If anybody has any ideas on how to achieve this I’d greatly appreciate it!

For starters your movement can just be in Update(), as FixedUpdate() is more physics based.

And secondly, the use of the boolean shows you want it to be a “one press” and just have it do what it does, then allow you to move again after. If I assume correctly, then you need more of something like this:

``````public class Player_Movement : MonoBehaviour
{
private Rigidbody rb;
private Vector3 inputDelta, shiftLeft = new Vector3 (-2, 0, 0), shiftRight = new Vector3(2, 0, 0);
private float moveSpeed = 100f, jumpHeight = 50f;
private bool jump = false, isGrounded = true, moveLeft = false, moveRight = false;
private int currentLane = 2;

// assuming lane positions are 10
float laneWidth = 10f;
float currentX;
float destinationX;
float speed = 100f;
void Start()
{
rb = this.GetComponent<Rigidbody>();
}
void Update()
{
inputDelta.x = Input.GetAxisRaw("Horizontal");
if (inputDelta.x > 0 && currentLane != 3 && !moveRight && !moveLeft)
{
moveRight = true;
currentX = transform.position.x;
destinationX = currentX + laneWidth;
moveSpeed = speed;
}
if (inputDelta.x < 0 && currentLane != 1 && !moveLeft && !moveRight)
{
moveLeft = true;
currentX = transform.position.x;
destinationX = currentX - laneWidth;
moveSpeed = -speed;
}
if ((Input.GetKeyDown(KeyCode.Space) || Input.GetKeyDown(KeyCode.W)) && isGrounded)
{
jump = true;
}

if (moveRight)
{
transform.Translate(moveSpeed * Time.deltaTime, 0, 0);
if (transform.position.x >= destinationX)
{
transform.position = new Vector3(destinationX, 0, 0);
currentLane += 1;
moveRight = false;
}
}
if (moveLeft)
{
transform.Translate(moveSpeed * Time.deltaTime, 0, 0);
if (transform.position.x <= destinationX)
{
transform.position = new Vector3(destinationX, 0, 0);
currentLane -= 1;
moveLeft = false;
}
}
}
}
``````

But if you want to cancel mid-move from going right, and say go back to left, it would require more coding. And declaring each lanes X value, would need to be done more proper than what I quickly wrote out. Also might help to use an enum for this as you can handle booleans better:

``````public enum MovingState
{
Idle,
Moving,
Left,
Right
}
public MovingState state;

//Update
if (state == MovingState.Right)
{
transform.Translate(speed);
// etc...
}
``````

But you’ll have to play around with it, to find what way suits you best. In my view, that’s what makes coding fun. The whole “well, what if I try this…”. So keep at it! Cheers!

There’s a LOT of duplicate code and really hairy if() statements above.

I would keep this far simpler.

• Track the lane number as an integer from 0 to n-1
• Update it based on input
• Clamp it based on range
• Compute a desired position for your player
• Smoothly move your player to that position

That’s it. My reference:

``````using UnityEngine;

// @kurtdekker - lane-based mover
//
// To use:
// Drop this on your player object
// Move your camera to see it go into the distance (see note about 2D below)
// press PLAY
// use A and D to change lanes

public class LaneMover : MonoBehaviour
{
private int laneNumber;

const int MaxLanes = 3;

const float LaneWidth = 2.0f;

const float LaneZeroXPosition = -LaneWidth * (MaxLanes - 1) / 2.0f;

const float LateralLaneMoveSpeed = 10.0f;

const float ForwardPlayerSpeed = 5.0f;

void Update()
{
// gather input to change lanes
if (Input.GetKeyDown( KeyCode.A)) laneNumber--;
if (Input.GetKeyDown( KeyCode.D)) laneNumber++;

// now guard laneNumber to MaxLanes lanes
if (laneNumber < 0) laneNumber = 0;
if (laneNumber > MaxLanes - 1) laneNumber = MaxLanes - 1;

// where should we be for this lane?
float laneXPosition = laneNumber * LaneWidth + LaneZeroXPosition;

// working copy
Vector3 position = transform.position;

// compute desired lateral position
position.x = Mathf.MoveTowards(
position.x,
laneXPosition,
LateralLaneMoveSpeed * Time.deltaTime);

// move the player downrange (change this to position.y for 2D games!)
position.z += ForwardPlayerSpeed * Time.deltaTime;

// off we go (replace with Rigidbody/Rigidbody2D.MovePosition() if using physics!)
transform.position = position;
}
}
``````
2 Likes