- Home /
How to make lane switching in mobile endless runner using UI buttons?
hey,
I am currently working on an endless runner game for smartphone where user can switch lanes by pressing UI buttons (one for left and another one for the right). Currently, I am able to make the player move left right by pressing buttons like in this video: link:VIDEO
but I want to create two-three lanes where user can move right left on those lanes like in temple run.
here is the code I have written so far:
[SerializeField] float moveSpeed = 10000f;
[SerializeField] float Padding=100f;
[SerializeField] float increment = 20f;
float axis = 20f;
float directionX,xMin,xMax;
Rigidbody2D rb;
private void Start()
{
SetUpMoveBoundaries();
rb = GetComponent();
}
private void Update()
{
Move();
}
private void SetUpMoveBoundaries()
{
Camera gameCamera = Camera.main;
xMin = gameCamera.ViewportToWorldPoint(new Vector3(0, 0, 0)).x+Padding;
xMax = gameCamera.ViewportToWorldPoint(new Vector3(1, 0, 0)).x-Padding;
}
private void Move()
{
directionX = CrossPlatformInputManager.GetAxis("Horizontal") * moveSpeed * Time.deltaTime;
rb.velocity = new Vector2(directionX, 0);
transform.position = new Vector2(Mathf.Clamp(transform.position.x, xMin, xMax), transform.position.y);
} }
Answer by highpockets · Jun 19, 2019 at 08:40 AM
EDIT: I do see in your code that you are not using ViewportToWorldPoint() properly.
Since you were not passing a 3rd parameter to the ViewportToWorldPoint method it doesn't matter what you pass to the first parameter (x position), it will always return the camera x, y and z position. So you needed to pass the last parameter instead of leaving it 0.0f. It is the distance the camera is in world space from the plane that you want to translate the point to. Therefore, you should be passing the distance from your player to the camera:
float dist = (Camera.main.transform.position - player.transform.position).magnitude;
Here is some tested code that I believe does what you want. I'm not sure if you wanted the dampening effect, but it is easy enough to remove if not:
[SerializeField] float moveSpeed = 10000f;
[SerializeField] float Padding = 2f;
[SerializeField] float increment = 20f;
[SerializeField] int currentLane = 2; //start in the middle lane
int nextLane;
float[] lanes = new float[3];
float targetXPos;
float axis = 20f;
float speed;
float maxChangeLaneSpeed = 10.0f;
float laneSeparation;
float directionX, xMin, xMax;
Rigidbody2D rb;
bool changingLane = false;
private void Start()
{
speed = maxChangeLaneSpeed;
SetUpMoveBoundaries();
rb = GetComponent<Rigidbody2D>();
targetXPos = lanes[currentLane - 1];
nextLane = currentLane;
}
private void Update()
{
Move();
}
private void SetUpMoveBoundaries()
{
Camera gameCamera = Camera.main;
float dist = (gameCamera.transform.position - transform.position).magnitude;
xMin = gameCamera.ViewportToWorldPoint(new Vector3(0, 0, dist)).x + Padding;
lanes[0] = xMin;
xMax = gameCamera.ViewportToWorldPoint(new Vector3(1, 0, dist)).x - Padding;
lanes[2] = xMax;
laneSeparation = Mathf.Abs(xMax - xMin)* 0.5f;
lanes[1] = xMin + laneSeparation;
transform.position = new Vector3(lanes[currentLane - 1], transform.position.y, transform.position.z);
}
private void Move()
{
if (Input.GetKey(KeyCode.A))
{
directionX = -1.0f;
}
else if(Input.GetKey(KeyCode.D))
{
directionX = 1.0f;
}
else
{
directionX = 0.0f;
}
if (directionX > 0.0f && currentLane < 3 && currentLane == nextLane)
{
targetXPos = lanes[currentLane];
nextLane = currentLane + 1;
speed = maxChangeLaneSpeed;
}
else if (directionX < 0.0f && currentLane > 1 && currentLane == nextLane)
{
targetXPos = lanes[currentLane - 2];
nextLane = currentLane - 1;
speed = maxChangeLaneSpeed;
}
if (nextLane > currentLane)
{
rb.velocity = new Vector2(speed, 0);
if (targetXPos <= transform.position.x)
{
DestinationReached();
}
}
else if (nextLane < currentLane)
{
rb.velocity = new Vector2(-speed, 0);
if (targetXPos >= transform.position.x)
{
DestinationReached();
}
}
//transform.position = new Vector2(Mathf.Clamp(transform.position.x, xMin, xMax), transform.position.y);
if (Mathf.Abs(targetXPos - transform.position.x) < laneSeparation)
{
float speedRegulator = Mathf.Abs(targetXPos - transform.position.x) / laneSeparation;
float minSpeedRegulator = 0.2f;
if(speedRegulator > minSpeedRegulator)
{
speed = maxChangeLaneSpeed * (Mathf.Abs(targetXPos - transform.position.x) / laneSeparation);
}
else
{
speed = maxChangeLaneSpeed * minSpeedRegulator;
}
}
}
void DestinationReached()
{
currentLane = nextLane;
rb.velocity = Vector2.zero;
transform.position = new Vector3(targetXPos, transform.position.y, transform.position.z);
}
I did not use the CrossPlatformInputManager as I got some errors when importing the package, but you can implement them easy enough. At the moment, left and right is A and D. Cheers
I am using SetUp$$anonymous$$oveBoundaries() function to prevent my player moving offScreen.
x$$anonymous$$in & x$$anonymous$$ax are the variables that contain $$anonymous$$imum & maximum location, my player can move on the x coordinate.
& then using transform.position = new Vector2($$anonymous$$athf.Clamp(transform.position.x, x$$anonymous$$in, x$$anonymous$$ax), transform.position.y); in $$anonymous$$ove() function so that my player can move left right when button is presed.
Right now my player moves smoothly but what I want is to make it move like the player in temple run or subway surfer.
Your answer
Follow this Question
Related Questions
Mobile 2d Game Resolution scalling 0 Answers
4 C# errors Endless Runner 0 Answers
Place UI objects on the top and bottom of screen object(2D sprite) 0 Answers
Why do I have to double click on a button the first time? 4 Answers
Clicking a button will display that buttons text in a seperate text-field 1 Answer