- Home /
The tail on my 2d snake game keeps infinitely spawning and I can't find the issue
I feel like it may be a quick fix or something, and sometimes it works normally but 80% of the time it infinitely spawns a tail whenever it eats the food. I have another food script that spawns the food in and that works fine but the problem comes whenever the snake eats the first piece of food and the tail keeps growing. I don't even know if I am putting my code in right but any help would be appreciated thank you!
public class Snake : MonoBehaviour {
//Game Over Text
public TextMeshProUGUI gameOverText;
//Manages the Tail
List <Transform> tail = new List<Transform>();
// Tail Prefab
public GameObject tailPrefab;
public bool isGameActive=true;
// snake moving to the right by default
public Vector2 dir = Vector2.right;
// Did the snake eat something?
public bool ate = false;
void Start() {
// Move the Snake every 100ms
InvokeRepeating("Move", 0.1f, 0.1f);
}
// Update is called once per frame
void Update() {
// Move snake in a new direction
if (Input.GetKey(KeyCode.RightArrow))
dir = Vector2.right;
else if (Input.GetKey(KeyCode.DownArrow))
dir = -Vector2.up;
else if (Input.GetKey(KeyCode.LeftArrow))
dir = -Vector2.right;
else if (Input.GetKey(KeyCode.UpArrow))
dir = Vector2.up;
}
void Move() {
if (isGameActive){
// Save current position of the snake
Vector2 v = transform.position;
// Move the snake's head
transform.Translate(dir);
// Ate something? Then insert new Element into gap
if (ate) {
// Load the next part of the tail into the world
GameObject g =((GameObject)Instantiate(tailPrefab, v, Quaternion.identity));
// Reset the snake so it is no longer eating anything
ate = false;
// put it in the tail list
tail.Insert(0, g.transform);
}
//adds new game object on the end
else if (tail.Count > 0) {
// Move last Tail Element to where the Head was
tail.Last().position = v;
// Add to front of list, remove from the back
tail.Insert(0, tail.Last());
tail.RemoveAt(tail.Count-1);
}
}
}
void OnTriggerEnter2D(Collider2D coll) {
// when it collides with food
if (coll.name.StartsWith("food prefab(Clone)")) {
// Get longer in next Move call
ate = true;
// get rid of the food
Destroy(coll.gameObject);
}
// Collided with Tail or Border
else if(coll.name.StartsWith("BorderLeft")){
gameOverText.gameObject.SetActive(true);
isGameActive=false;
}
}
}
Answer by bubzy · May 31, 2021 at 07:34 AM
if (ate) {... ...else if (tail.Count > 0) {...
these aren't really variables to be comparing.
else if (tail.Count > 0) {
could just be if(tail.Count > 0) {
also, does the food object get destroyed? have you checked the status of the boolean ate
?
No, he needs / wants the else. Otherwise he would always remove the last piece and put two pieces in the same place. The idea is that the snake advances one tile every "Move" tick. When the snake ate something, we will just move the head and insert a new tile in the gap. We keep the rest of the tail where it is in order for the snake to grow. If we did not eat something, only then we want to fill the gap with the last element from the list. So yes, he needs the "else". So your fix is not really a fix ^^.
Though your suggestion to actually debug the problem is spot on.
Since the game is on a slow tick I would suggest to lower the tick rate for debugging from 100ms to 1000ms or slower. Keep in $$anonymous$$d that you can press the pause button in Unity to halt the game after the frame has finished. It gives you time to inspect objects.
Next suggestion: give each tail object an increasing name. Just use another int variable that you simply count up whenever you create a new tail and include that int in the name of the instantiated tail object. This makes it easier to identify the different objects in the scene / hierarchy.
Finally you can always attach Visual Studio as debugger to the Unity editor, set breakpoints in your code and step through your code to see what it does and to inspect individual variables. Note when the execution is stopped with the debugger in VS, the Unity editor will not respond anymore. The debugger is literally freezing the editor in that state. You have to continue playing without hitting a breakpoint in order to switch to Unity. As I said, the Unity editor can only be paused in between frames with the pause button in the Unity editor itself. You can call Debug.Break from code which does the same as pressing the pause button manually. It will halt your game after the current frame.
So learn to use the debug tools available.
ah I just skimmed the code, should probably pay more attention when offering answers. :)
Your answer
Follow this Question
Related Questions
Creating a chase obejct for 2D infinite Runner 0 Answers
Move the player along the centre of a spawned tile in an infinite runner game 0 Answers
Moving a character whilst also aiming with a crosshair TPS 1 Answer
Smooth camera follow does not keep up with increasing velocity 0 Answers
Rigidbody2d.velocity making character stop in between 1 Answer