I’m building a learning project that uses stepwise movement in a 2.5D space–imagine a first person 3d maze where you can move from square to square in discrete steps. For translation in X,Z I’ve followed what seems to be the standard smooth movement technique. Works like a charm.
When I try and introduce rotation an intermittent bug appears. The ability to translate, to move in the X or Z direction, occasionally stops. Rotation is still possible and eventually will ‘unlock’ translation again, but I can’t spot the pattern of what is causing translation to lock up. I’ve tried to simplify the rotation part as much as possible. The current code doesn’t interpolate it just jumps the transform.rotation as needed.
private bool isMoving; // disable input while executing movement
private void Update()
{
GetInput();
}
private void GetInput()
{
// NB: Need to enforce one key at a time
bool turnRight = Input.GetKeyDown("e");
bool turnLeft = Input.GetKeyDown("q");
float forwardBack = Input.GetAxis("Vertical");
float leftRight = Input.GetAxis("Horizontal");
if (!isMoving)
{
if (forwardBack != 0 || leftRight != 0)
{
Vector3 direction = MovementDirection(forwardBack, leftRight);
Move(direction);
}
if (turnRight)
{
Rotate(90);
}
if (turnLeft)
{
Rotate(-90);
}
}
}
private Vector3 MovementDirection(float forwardBack, float leftRight)
{
string facing = GetFacingString(); // This method looks at transform.rotate and returns a string (NSEW)
Vector3 direction = Vector3.zero;
if (forwardBack > 0)
{
// Move forward
switch (facing)
{
case "N":
direction = Vector3.forward;
break;
case "S":
direction = Vector3.back;
break;
case "E":
direction = Vector3.right;
break;
case "W":
direction = Vector3.left;
break;
}
}
// ... I've truncated the code here for readability. MovementDirection is just a
// series of if/switch statements determining the correct Vector3 to return
//(Vector3.forward, back, left, right) based on player facing ...//
return direction;
}
private bool Move(Vector3 direction)
{
// Scale direction by map scale
direction = direction * LevelManager.scale;
// LevelManager.scale = 5. The cells are 5x5 in size and the player is in the center.
Vector3 end = transform.position + direction;
// Add code to test if movement is blocked--return false if fails
StartCoroutine(SmoothMovement(end));
return true;
}
private IEnumerator SmoothMovement(Vector3 end)
{
// create variable to store remaining translation distance
float sqrRemainingDistance = (transform.position - end).sqrMagnitude;
isMoving = true;
while (sqrRemainingDistance > float.Epsilon) // Close enough
{
// determine intermediate position. Use Time.deltaTime to calculate total number of 'steps' required.
Vector3 newPosition = Vector3.MoveTowards(transform.position, end, Time.deltaTime * speed);
// move player to intermediate position
transform.position = newPosition;
// compute new remaining distance;
sqrRemainingDistance = (transform.position - end).sqrMagnitude;
yield return null;
}
transform.position = end; // avoid any drift
isMoving = false;
}
private void Rotate(float degrees)
{
isMoving = true;
//transform.Rotate(new Vector3(0, degrees, 0));
transform.Rotate(Vector3.up, degrees);
//StartCoroutine(SmoothRotation(end));
isMoving = false;
}
If I eliminate the rotation component I can translate as long as I care to. But enabling the rotation code causes the issue every execution time. Any suggestions on how I can troubleshoot this issue are greatly appreciated.