- Home /
Problem with Snake Game(input help)
I'm creating the classic snake game in Unity but I'm having trouble with my code that controls the direction of the snake. I have the snake "head" and body all in an array, in which i then update each position to the position of the object in front of it using a simple timer. Each tick of the timer also moves the snake 1 unit in a direction based on the input from the user.
The problem I'm having is since everything is working under a timer / tick in the update function. Sometimes the input doesnt get called even though its been pressed, due to the function that controls movement is inside the timer. Though if I put that input function outside the timer it creates a problem in which the player can move into itself if inputed directions very quickly.
I'm not wording my problem well at all and I'm sorry for that.. Here is some of my code that is attached to the snake object.
// Update is called once per frame
void Update() {
if(!isDead){
sinceLastTick += Time.deltaTime;
//My tick timer that updates position of snake
if(sinceLastTick > tickTime){
//Gets input from arrow key
HeadMovement();
//updates each position of object in array to object in front(follow snake head)
DrawSnake();
//move snake
cached.position += direction;
sinceLastTick -= tickTime;
}
}
}
//Keeps track of user input and stores vector 3 in 'direction' var
private void HeadMovement() {
if(Input.GetKey("up") && !down) {
up = true;
down = false;
left = false;
right = false;
//This is where we store our vector3 to get called each tick (mygrid.up == vector3.up)
direction = myGrid.up;
}
else if( Input.GetKey ("down") && !up){
up = false;
down = true;
left = false;
right = false;
direction = -myGrid.up;
}
else if(Input.GetKey ("left") && !right ){
up = false;
down = false;
left = true;
right = false;
direction = -myGrid.right;
}
else if(Input.GetKey ("right") && !left){
up = false;
down = false;
left = false;
right = true;
direction = myGrid.right;
}
}
//Method to draw each snake and update position
private void DrawSnake() {
//for every object in list
for (int i = (snakeUpdate.Count - 1); i > 0; i--){
//give that object the position of object in front
snakeUpdate[i].transform.position = snakeUpdate[i-1].transform.position;
}
}
I just cant wrap my head around the logic anymore, I know if i move my HeadMovement() function outside of the tick timer then it grabs input quicker then the snake can update itself (DrawSnake()) so it makes it able to turn into itself.
let me know if you have any questions. Thanks.
Answer by robertbu · Feb 19, 2014 at 06:29 AM
In Update(), every frame, collect a possible new direction. Get rid of up/down/left/right and the direction check for each key. Just do:
if (Input.GetKeyDown(KeyCode.UpArrow)) nextDir = myGrid.up;
else if (Input.GetKeyDown(KeyCode.DownArrow)) nextDir = -myGrid.up;
else if (Input.GetKeyDown(KeyCode.LeftArrow)) nextDir = -myGrid.right;
else if (Input.GetKeyDown(KeyCode.RightArrow)) nextDir = myGrid.right;
Then when you go to your timed step code, do:
if (-nextDir != direction) {
direction = nextDir;
}
That way the user can press any number of keys. You only process the last one, and you only use it if the direction does not conflict.
Thanks for the post! I'm going to try that tomorrow morning! I will post a build so you can try yourself and maybe get the feeling of the unresponsive input.
So it sometimes still feels unresponsive, like it doesnt grab the input in time. (I think it has something to do with the tick/timer if statement that executes the code)
I have a dropbox webplayer for you to try out and maybe you can get the same feeling I have.
Edit: Took down dropbox link
I can see how your original code would have this problem. But if you rewrite the script as I indicated, it should fix the problem. Post your modified script here, and I'll take another look.
This is how I have it right now and it still feels a bit unresponsive
// Update is called once per frame
void Update() {
if(!isDead){
sinceLastTick += Time.deltaTime;
if (Input.Get$$anonymous$$ey($$anonymous$$eyCode.UpArrow)) nextDir = myGrid.up; else if (Input.Get$$anonymous$$ey($$anonymous$$eyCode.DownArrow)) nextDir = -myGrid.up; else if (Input.Get$$anonymous$$ey($$anonymous$$eyCode.LeftArrow)) nextDir =-myGrid.right; else if (Input.Get$$anonymous$$ey($$anonymous$$eyCode.RightArrow)) nextDir = myGrid.right;
//$$anonymous$$y tick timer that updates position of snake
if(sinceLastTick > tickTime){
if(-nextDir != direction){
direction = nextDir;
}
//updates each position of object in array to object in front(follow snake head)
DrawSnake();
//move snake
cached.position += direction;
sinceLastTick -= tickTime;
}
}
}