- Home /
Jittery Constant Grid Movement
Hello everyone,
I just started using Unity this past week. To get some practice I decided to make a Pacman/Snake hybrid. Eat cubes that are randomly generated, simple enough. At first I had a simple movement system that moved the player in a direction so long as the key was pressed. Ideally, I wanted to have grid like movement that also remembered your last key press to keep you going in one direction without having to hold a key down.
Without having to dive into code, I'll go into the implementation just a little. I keep track of current direction and new direction. So long as we are not at a bound/wall, we will to the next point in our grid. Once we hit a point we check to see if a new direction was pressed, and there was we set it to current.
I implemented this separately to make sure I understood how both worked, and they performed just fine. However, once I put them together things went downhill. Yes, they both technically work together, but not how I'd like. Rather than a smooth continuous line I get constant movement that pauses at each point. I've tried rearranging things, lowering settings (the FPS script showed 60+), trying to optimize my code, etc. Nothing has worked, so I figured I'd use my resources!
Here is the script attached to my Player object
using UnityEngine;
using System.Collections;
public class PlayerScript : MonoBehaviour {
enum Directions:int {NONE, UP, DOWN, LEFT, RIGHT};
public float movementSpeed = 10;
Vector3 nextPosition = default(Vector3);
bool onRouteToDestination = false;
Directions newDirection = Directions.NONE;
Directions currentDirection = Directions.NONE;
// Update is called once per frame
void Update () {
// Set the players direction. We check their current direction to see if
// the key pressed is a NEW direction. If it is we queue it up.
if(Input.GetButtonDown ("RIGHT") && currentDirection != Directions.RIGHT){
if(currentDirection == Directions.NONE){
currentDirection = Directions.RIGHT;
}
else{
newDirection = Directions.RIGHT;
}
}
else if(Input.GetButtonDown ("LEFT") && currentDirection != Directions.LEFT){
if(currentDirection == Directions.NONE){
currentDirection = Directions.LEFT;
}
else{
newDirection = Directions.LEFT;
}
}
else if(Input.GetButtonDown ("UP") && currentDirection != Directions.UP){
if(currentDirection == Directions.NONE){
currentDirection = Directions.UP;
}
else{
newDirection = Directions.UP;
}
}
else if(Input.GetButtonDown ("DOWN") && currentDirection != Directions.DOWN){
if(currentDirection == Directions.NONE){
currentDirection = Directions.DOWN;
}
else{
newDirection = Directions.DOWN;
}
}
// If we do not have a destination, and we are moving, calculate our next point
if(onRouteToDestination == false && currentDirection != Directions.NONE){
// Calculate our desired position
if(currentDirection == Directions.RIGHT){
nextPosition = new Vector3(transform.localPosition.x+0.5f,transform.localPosition.y,transform.localPosition.z);
}
else if(currentDirection == Directions.LEFT){
nextPosition = new Vector3(transform.localPosition.x-0.5f,transform.localPosition.y,transform.localPosition.z);
}
else if(currentDirection == Directions.UP){
nextPosition = new Vector3(transform.localPosition.x,transform.localPosition.y,transform.localPosition.z+1);
}
else if(currentDirection == Directions.DOWN){
nextPosition = new Vector3(transform.localPosition.x,transform.localPosition.y,transform.localPosition.z-1);
}
// We're good to go!
onRouteToDestination = true;
// Also make sure that our next point is within bounds
// If it isn't, put a halt to this vacation
// Check Left, Right, Top, and Bottom bounds
if(nextPosition.x > 4.75f || nextPosition.x < -4.75f ||
nextPosition.z > 4.50f || nextPosition.z < -4.50f){
onRouteToDestination = false;
currentDirection = newDirection;
newDirection = Directions.NONE;
}
}
// Time to move (or continue moving)
if(onRouteToDestination){
// Check to see if the points are approximatly the same
if(!Mathf.Approximately(Vector3.Distance(transform.localPosition,nextPosition),0f)){
if(currentDirection == Directions.RIGHT){
transform.Translate(new Vector3(movementSpeed*Time.deltaTime, 0, 0));
if(transform.localPosition.x > nextPosition.x){
transform.localPosition = nextPosition;
}
}
else if(currentDirection == Directions.LEFT){
transform.Translate(new Vector3(-movementSpeed*Time.deltaTime, 0, 0));
if(transform.localPosition.x < nextPosition.x){
transform.localPosition = nextPosition;
}
}
else if(currentDirection == Directions.UP){
transform.Translate(new Vector3(0, movementSpeed*Time.deltaTime, 0));
if(transform.localPosition.z > nextPosition.z){
transform.localPosition = nextPosition;
}
}
else if(currentDirection == Directions.DOWN){
transform.Translate(new Vector3(0, -movementSpeed*Time.deltaTime, 0));
if(transform.localPosition.z < nextPosition.z){
transform.localPosition = nextPosition;
}
}
}
else{
onRouteToDestination = false;
if(newDirection != Directions.NONE){
currentDirection = newDirection;
newDirection = Directions.NONE;
}
}
}
}
}
I've looked over it quite a few times now and nothing really sticks out as computationally difficult, aside from my Approximately and Distance. I'm not sure what the overhead is on calling those. Either way, if anyone could help me out in the slightest bit I would be grateful.
To get a better feel, I uploaded this buggy version to my website. The last working one can be found here.
Note: I had used StartCoroutine before that called a method that would then figure out my next point and move. This worked, but the object moved at a ridiculous rate (using the same calculation I'm doing now as well as entering in a small number manually).