Ashane Alvis Ashane Alvis - 3 months ago 13
C# Question

How do I accurately switch lanes with my script?

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 lanes, 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 fix it?

I came to notice that the character's x axis, the point values increases little 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;
}
}

Answer

Fairly simple, in the section of code where you check whether the current position of your character is close to the final position, also set the final position.

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

The reason this happens is essentially how the Update function works. Monobehaviour's Update is NOT called on a fixed time step (what we call Time.deltaTime). Therefore, in most cases, your character's position is going to over/undershoot the final value.

Comments