Issues with snake game in C#
Hello! It is my first time posting in this forum. Please bear with me, I'm a huge amateur.
So, one of the first things I wanted to do when I started to learn coding was to make a snake game.
Today, I decided I was ready for that! And things were going pretty well, except for an issue.
Here is how the game works: You(square), the player, start the game by automatically moving to the right. The left and right arrow keys change your angle by 90º. A single piece of food(circle) spawns at the beginning of the game and, when you touch it, it disappears and allows for another food piece to spawn, and so on. I still haven't implemented any kind of progress in the game yet.
However, when the player catches the food, its direction starts going wonky. Instead of staying on the perfect up/down/left/right axis, it drifts a little bit with every new movement. So now I have to do one of two things:
a) fix the controls and make something better;
b) fix this particular issue somehow.
The scripts involved are two, both attached to the player.
Player Movement Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float speed = 0.5f;
void Start()
{
transform.position = new Vector3(0, 0, 0);
}
void Update()
{
//starts the player going into the right direction(how poetic!)
transform.localPosition += transform.right * speed * Time.deltaTime;
Debug.Log("test");
changeDirection();
}
//will change the angle of the player 90 degrees
void changeDirection() {
if (Input.GetKeyDown(KeyCode.RightArrow))
{
RotateLeft();
}
else if (Input.GetKeyDown(KeyCode.LeftArrow))
{
RotateRight();
}
}
void RotateLeft()
{
transform.Rotate(Vector3.forward * -90);
}
void RotateRight()
{
transform.Rotate(Vector3.forward * +90);
}
}
And the script to eat the food:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EatFood : MonoBehaviour
{
public SpawnFood spawnFood;
void OnCollisionEnter2D(Collision2D transformCollision)
{
if (transformCollision.gameObject.tag == "Food")
{
Destroy(GameObject.FindWithTag("Food"));
spawnFood.maySpawn = true;
}
}
}
I believe the issue started when I imported the boolean from the food spawning script.
What can I do here?
PS: How do I make paragraphs? hehe
[1]: /storage/temp/133284-capturar.png
Answer by DCordoba · Feb 20, 2019 at 01:52 PM
well the problem is, I think, the physics about the collider I'am not very good explaining it, please forgive me if I mess instead of explain
when you collide a object, it change a bit its direction, you know, like on normal life both objects act following the newtonian's repulsion? law.
so the forward isn't anymore pointing straight is, a little pushed off
after this small change, you expand the error taking the forward of the object to continue the rotation, each time you move, you add this slighty difference to the total
you can, as you already said:
a) change controls: the old snake game change dir relative to the map, not the snake, so if you press up it go to the up of the map, didn't keep going forward
void changeDirection() {
if (Input.GetKeyDown(KeyCode.RightArrow)){
GoLeft();
} else if (Input.GetKeyDown(KeyCode.LeftArrow)){
GoRight();
}else if (Input.GetKeyDown(KeyCode.UpArrow)){
GoUp();
}else if (Input.GetKeyDown(KeyCode.DownArrow)){
GoDown();
}
}
void GoLeft()
{
transform.right= Vector3.left;
}
void GoRight()
{
transform.right = Vector3.right;
}
void GoUp()
{
transform.right = Vector3.up;
}
void GoUp()
{
transform.right = Vector3.down;
}
}
b) just solve the problem: to evade physics affect the collider but keeping it detecting collisions, use trigger, so set snake head collider as a trigger and start catching it with OnTriggerEnter in this case, you need to change the line 9 of EatFood by
void TriggerEnter2D(Collider2D transformCollision){
you will need to change the rest scripts that manage collisions, like the walls
and in order to correctly, (both collider and triggers) activate it, I suggest change displacement from kinematic (using transform.position) to physics (using forces) change line 18 of PlayerMovement
by
snakeRigidbody2D.velocity = transform.right * speed * Time.deltaTime;
snakeRigidbody2D is... the rigidbody of the snake
bonus? xd, I suggest to use the info provided to the collider to destroy the object, Instead of searching food item on each pickup:
void OnCollisionEnter2D(Collision2D transformCollision) //or void TriggerEnter2D(Collider2D transformCollision){
{
if (transformCollision.gameObject.CompareTag("Food"))
{
Destroy(transformCollision.gameObject);
spawnFood.maySpawn = true;
}
}
Answer by DoritoFox · Feb 25, 2019 at 03:13 PM
@DCordoba Oh my god, thank you so much! I didn't expect such a detailed and thorough answer. I am very sorry for the late reply, college started last week for me and I have been very busy. I didn't get a chance to fully test out the code you sent me but I'm positive it works. Thank you so much again. This is really helpful!
Your answer
Follow this Question
Related Questions
2D AI movement 0 Answers
Move Player along normal of floor? 1 Answer
Snake movement from Snake VS Block 0 Answers
I can't seem to rotate my character depending on what side he is running to (2D sidescroller) 0 Answers
No overload for method. 1 Answer