Hello, the below code kind of works. The player moves in the correct direction, and jumps etc. but keeps moving in the presed direction until the opposite direction is pressed. Not sure why and i’ve been trying to figure it out for a while now to no avail. I want the player to move to a specific lane and stay there. Lane seperation is set to 2.3f.
private void Update()
{
if (controller == null)
return;
if ((Input.GetKeyDown(KeyCode.LeftArrow)))
{
SetLane(false);
}
if ((Input.GetKeyDown(KeyCode.RightArrow)))
{
SetLane(true);
}
// select lane
Vector3 targetPosition = transform.position.x * Vector3.zero;
switch (currentLane)
{
case -1:
targetPosition += Vector3.left * laneSeparation;
break;
case 0:
targetPosition = Vector3.zero;
break;
case 1:
targetPosition += Vector3.right * laneSeparation;
break;
default:
break;
}
// create vector to new lane
Vector3 moveVector = Vector3.zero;
moveVector.x = (targetPosition - transform.position).normalized.x * strafeSpeed;
// calculate y
if (IsGrounded())
{
verticalVelocity = -0.1f;
if (Input.GetKeyDown(KeyCode.Space))
{
// jump
verticalVelocity = jumpForce;
}
}
else
{
verticalVelocity -= gravity * Time.deltaTime;
// fast ground
if (Input.GetKeyDown(KeyCode.DownArrow))
{
verticalVelocity -= jumpForce;
}
}
moveVector.y = verticalVelocity;
moveVector.z = 0f;
// change lane
controller.Move(moveVector * Time.deltaTime);
}
private void SetLane(bool movingRight)
{
currentLane += (movingRight) ? 1 : -1;
currentLane = Mathf.Clamp(currentLane, -1, 1);
}
Try this - supports any number of lanes, should be a good starting point. You’ll need to add your jumping and maybe change things around a bit for whatever you’re doing but I’ve tested with a Cube and it’s working:smile:
using UnityEngine;
public class LaneExample : MonoBehaviour
{
public Transform controller;
private int currentLane = 0;
public int startingLane = 0;
public int leftmostLane = -1;
public int rightmostLane = 1;
public float laneSeparation = 2.3f;
public float strafeSpeed = 1;
private float strafeElapsed = -1;
private float strafeDuration = 0.25f;
private Vector3 fromPosition;
private Vector3 toPosition;
private void Start()
{
if (controller == null) return;
currentLane = Mathf.Clamp(startingLane, leftmostLane, rightmostLane);
controller.transform.position = Vector3.right * currentLane * laneSeparation;
}
private void Update()
{
if (controller == null) return;
if (Input.GetKeyDown(KeyCode.LeftArrow))
{
SetLane(currentLane - 1);
} else if ((Input.GetKeyDown(KeyCode.RightArrow)))
{
SetLane(currentLane + 1);
}
if (strafeElapsed != -1)
{
// only processed while moving
strafeElapsed += Time.deltaTime;
float progress = Mathf.Clamp(strafeElapsed / strafeDuration, 0.0f, 1.0f);
if (progress == 1) strafeElapsed = -1;
controller.transform.position = Vector3.Lerp(fromPosition, toPosition, progress);
// todo: handle jump during transition
// i.e. if (jumping) controller.transform.Translate(Vector3.up * elevation);
} else
{
// todo: handle jump while not moving
// i.e. if (jumping) controller.transform.position = toPosition + (Vector3.up * elevation);
}
}
private void SetLane(int lane)
{
if (lane == currentLane) return;
currentLane = Mathf.Clamp(lane, leftmostLane, rightmostLane);
strafeElapsed = 0;
fromPosition = controller.transform.position;
toPosition = Vector3.right * currentLane * laneSeparation;
strafeDuration = Vector3.Distance(fromPosition, toPosition) / strafeSpeed;
}
}
Not at my computer to test right now but it looks a lot more elegant than my own attempt. Thanks for writing out an entire script! Did not expect anyone to do that. One thing I should have mentioned is that “controller” in my script actually refers to a Character Controller component but I can make any necessary adjustments though.
Hope I’m not asking for too much now, but may I ask if you spotted what was wrong with my original script? I’ve never been great working with Vectors, so would love the learning point. If not, no problem; you already did enough. Thank you!
The .Move call would continue to move your character in that direction because nothing told it “we’ve arrived at the new position.”
Anyway my script was just done quickly, but worth nothing… it lets you interrupt lane change, if you press opposite direction quickly it will cancel and move back to the previous lane. It will also effectively “queue” presses of the keys, i.e. if you press left twice quickly, it will move until it’s 2 lanes left and stop there. Good luck with your project!
Oh wow, you’ve got to be kidding me… Now I feel stupid. I assumed my movement calculations weren’t right or something.
Yeah that’s ideal and will tie in nicely to what I’m doing so thanks again. I’ll be using swipes for moving the player and already have that written. Thanks for your help