- Home /
The question is answered, right answer was accepted
Snake game movement problem
Hello, currently learning how to make a snake game. The problem is that when user input two input very quickly, first input will be process but it won't update in the game. For example (the picture below ), Snake is currently moving right, and when I pressed down and left quickly, it will process the down button but won't update on the game and just turn left, which collide with the body which resulted in game over.
Here's the snake movement:
public class Snake : MonoBehaviour
{
Vector2 direction = Vector2.right;
void Start()
{
Time.timeScale = 1f;
InvokeRepeating(nameof(this.Move), 0.09f, 0.09f);
InvokeRepeating("Score", 5, 5);
}
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.RightArrow))
{
if (direction != Vector2.left)
{
direction = Vector2.right;
}
}
if (Input.GetKey(KeyCode.DownArrow))
{
if (direction != Vector2.up)
{
direction = Vector2.down;
}
}
if (Input.GetKey(KeyCode.LeftArrow))
{
if (direction != Vector2.right)
{
direction = Vector2.left;
}
}
if (Input.GetKey(KeyCode.UpArrow))
{
if (direction != Vector2.down)
{
direction = Vector2.up;
}
}
}
void Move()
{
if (GameController.isPaused) return;
Vector2 currentPos = transform.position;
transform.Translate(direction);
if (ate)
{
var newPart = (GameObject)Instantiate(tailPrefab, currentPos, Quaternion.identity);
tail.Insert(0, newPart.transform);
length+=5;
ate = false;
}
else if (tail.Count != 0)
{
tail.Last().position = currentPos;
tail.Insert(0, tail.Last());
tail.RemoveAt(tail.Count - 1);
}
if (poison)
{
{
Destroy(tail[tail.Count - 1].gameObject);
tail.RemoveAt(tail.Count - 1);
poison = false;
}
}
}
}
Answer by Anis1808 · Dec 03, 2019 at 12:12 AM
Can you try this ?
public class Snake : MonoBehaviour
{
Vector2 direction = Vector2.right;
Vector2 waitingDirection = Vector2.zero;
bool justChangedDirection, useNextDirection;
void Start()
{
Time.timeScale = 1f;
InvokeRepeating(nameof(this.Move), 0.09f, 0.09f);
InvokeRepeating("Score", 5, 5);
}
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.RightArrow))
{
if (direction != Vector2.left)
{
if(!justChangedDirection)
direction = Vector2.right;
justChangedDirection = true;
}else{
waitingDirection = Vector2.right;
}
}
}
if (Input.GetKey(KeyCode.DownArrow))
{
if (direction != Vector2.up)
{
if(!justChangedDirection)
direction = Vector2.down;
justChangedDirection = true;
}else{
waitingDirection = Vector2.down;
}
}
}
if (Input.GetKey(KeyCode.LeftArrow))
{
if (direction != Vector2.right)
{
if(!justChangedDirection)
direction = Vector2.left;
justChangedDirection = true;
}else{
waitingDirection = Vector2.left;
}
}
}
if (Input.GetKey(KeyCode.UpArrow))
{
if (direction != Vector2.down)
{
if(!justChangedDirection)
direction = Vector2.up;
justChangedDirection = true;
}else{
waitingDirection = Vector2.up;
}
}
}
}
void Move()
{
if (GameController.isPaused) return;
Vector2 currentPos = transform.position;
if(!useNextDirection){
transform.Translate(direction);
}else{
transform.Translate(direction);
useNextDirection = false;
}
if(justChangedDirection){
useNextDirection = true;
justChangedDirection = false;
}
if (ate)
{
var newPart = (GameObject)Instantiate(tailPrefab, currentPos, Quaternion.identity);
tail.Insert(0, newPart.transform);
length+=5;
ate = false;
}
else if (tail.Count != 0)
{
tail.Last().position = currentPos;
tail.Insert(0, tail.Last());
tail.RemoveAt(tail.Count - 1);
}
if (poison)
{
{
Destroy(tail[tail.Count - 1].gameObject);
tail.RemoveAt(tail.Count - 1);
poison = false;
}
}
}
}
Thanks, it work. but the snake is not moving smoothly since it has to wait to changed direction. So if I press down left quickly, before it just die. Now it won't take do anything since it hasn't turn down yet. Thanks for your help.
True, it does solve the problem i'm having. But now the control isn't smooth which will take the user experience away. I'm gonna try to see if I can make your code run smoother somehow. But still, thanks for the help and suggestion.
Answer by Larry-Dietz · Dec 02, 2019 at 06:43 PM
Try changing all the if's in your input checks (except the first one, to else if
That way there is at least 1 frame between processing the keys.
Where is $$anonymous$$ove being called from?
I would try adding the call to $$anonymous$$ove at the end of Update. As long as move gets called once between keypresses, this should work, as far as I can see (with the else if)
Call from the void start(){ InvokeRepeating(nameof(this.$$anonymous$$ove), 0.09f, 0.09f); } . I tried invoking move at the end of Update, but it update too fast which result in snake moving too quickly.
Follow this Question
Related Questions
Plane Processing 1 Answer
Updated from 5.3.3 to 5.3.4 and can't open project 1 Answer
Upgrading Unity from 2018.2.16 to 2019.2.16 broke my project 1 Answer
GLSL - Post processing? 0 Answers