# How do I accuratley switch lanes with my script?

Hi I'm working on a 3 lane 3d endless runner game and I came across this issue. With some help from this stack overflow, I managed to switch my character in the 3 lane, after couple of seconds my character slowly moves away from the lanes, simply rather than running a straight line on each lane, After switching the character moves away from the lane. It is really annoying. How do I fixed it? I came to notice that the character's x axis, the point values increases littlie by little. for e.g. If it is the right lane it should be 1.0000, but after switching it increases gradually 1.0045, 1.0345, 1.09585 so on and vise versa too. Also sometimes it also breaks the 3 lane movement and the character tries to move all the way to the right or left without stopping, so I have to stop play mode.

Help would be greatly appreciated.

Here's my script.

 //Variables for Lane switching
private bool isChangingLane = false;
private Vector3 locationAfterChanginLane = Vector3.zero;
private Vector3 sideWayMovementDistance = Vector3.right * 2f; // This might be the case that triggers abnormal movements
private float sideWaySpeed = 6f;

public enum Lane
{
Left,
Right,
Center
}

public enum MoveDirection
{
Left,
Right,
None
}

Lane currentLane = Lane.Center;

void Update()
{
currentBaseState = anim.GetCurrentAnimatorStateInfo(0);

if (controller.isGrounded)
{
verticalVelocity = -0.5f;
if (currentBaseState.fullPathHash == locoState)
{
if (Input.GetButtonDown("Jump"))
{
verticalVelocity = 18f;

anim.SetBool("Jump", true);
}
else if (Input.GetKeyDown(KeyCode.S))
{
anim.SetBool("Slide", true);
}

}

MoveLeftRight(); // This is the method to move right and left.

if (isChangingLane)
{
if (Math.Abs(transform.position.x - locationAfterChanginLane.x) < 0.1f)
{
isChangingLane = false;
moveVector.x = 0;
}
}

}
}

private void MoveLeftRight()
{

MoveDirection requestedMoveDirection = MoveDirection.None;
if (Input.GetKeyDown(KeyCode.A) && !isChangingLane)
{
requestedMoveDirection = MoveDirection.Left;
isChangingLane = true;
}
else if (Input.GetKeyDown(KeyCode.D) && !isChangingLane)
{
requestedMoveDirection = MoveDirection.Right;
isChangingLane = true;
}

switch (requestedMoveDirection)
{
case MoveDirection.Right:
if (currentLane == Lane.Right)
{
Debug.Log("Right Lane");
break; //Do nothing when in right lane.

}
else if (currentLane == Lane.Center)
{
locationAfterChanginLane = transform.position + sideWayMovementDistance;
moveVector.x = +sideWaySpeed;

currentLane = Lane.Right;
Debug.Log("Center --> Right");
}
else if (currentLane == Lane.Left)
{
locationAfterChanginLane = transform.position + sideWayMovementDistance;
moveVector.x = +sideWaySpeed;

currentLane = Lane.Center;
Debug.Log("Left --> Center");
}
break;
case MoveDirection.Left:
if (currentLane == Lane.Left)
{
Debug.Log("Left Lane");
break; //Do nothing when in left lane.
}
else if (currentLane == Lane.Center)
{
locationAfterChanginLane = transform.position - sideWayMovementDistance;
moveVector.x = -sideWaySpeed;

currentLane = Lane.Left;

Debug.Log("Center --> Left");
}
else if (currentLane == Lane.Right)
{
locationAfterChanginLane = transform.position - sideWayMovementDistance;
moveVector.x = -sideWaySpeed;

currentLane = Lane.Center;

Debug.Log("Right --> Center");
}
break;
}
}


I would suggest setting a Clamp. I created my own for some lighting effects like this:

public static float Clamp(float val, float min, float max)
{
return (val < min) ? min : (val > max) ? max : val;
}


You can then change a global variable for min/max, maybe just setting them both to a static value. This can be run during update to constantly keep the float from sliding out of where you want it to be. You could also use this with a slight variation of min/max to allow a slight swaying movement as your player runs, which could look pretty awesome depending on the rest of the game.

In this case, val is whatever the current value is. So you might switch to a planar value (the one that your player sways from now), then Clamp to +/- 0.01 of that value. So let's say you want your x value to be 1.25f. You move the character to 1.25f and then Clamp against that in your update with something like:

 leftLaneMin = 1.24f;
leftLaneMax = 1.26f;
centerLaneMin = 2.49f;
centerLaneMax = 2.51f;
rightLaneMin = 3.74f;
rightLaneMax = 3.76f;

laneValue = leftLaneMin;
player.x = (laneValue, leftLaneMin, leftLaneMax);


That would keep player.x "stick" between 1.24f and 1.26f.

• Any luck? Please mark as answered if it did. If not, let me know and I'll see what else I can do. :) – Jesse Williams Aug 16 '16 at 18:30
• I finally managed to stop the issue but arising another problem. The character jerks backward in the z axis. I asked this question in here If you can make resolve this it would be great. Thanks for reaching out too. :) – Ashane Alvis Aug 16 '16 at 18:42
• Also if you can elaborate your answer further like what is val, It would be great. – Ashane Alvis Aug 16 '16 at 18:45
• Hi @Jesse, Thanks a lot sir. It solved my problem. I'm so happy. Thanks again. :D – Ashane Alvis Aug 19 '16 at 17:56
• @AshaneAlvis happy to help. Glad it worked out :) – Jesse Williams Aug 19 '16 at 17:59

If your character is still moving after it changes lanes. You might want to set a variable of boolean to lock that specific axis while he's running. I am thinking it is moving because of the physics on the engine.

You can lock an axis in the editor. Or you can do it also on the script.

• I can see how this would be a correct answer, but it is very vague. Perhaps you could elaborate? Its also worth addressing that in the case of using RigidBody or RigidBody2D, the component itself gives the ability to lock the axis for both translation (movement) and rotation. – Gnemlock Aug 15 '16 at 1:18