I'm trying to make an google snake like game and I got the movement all right but it doesn't flip up and down. If I click A and D on my keyboard it flips left and right, but if I click W or S it flips left or right for some reason.
Here is my code:
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class snakemovement : MonoBehaviour
{
private Vector2 _direction = Vector2.right; bool facingRight = true;
void Update()
{
if (Input.GetKeyDown(KeyCode.W))
{
_direction = Vector2.up; Flip();
}
else if (Input.GetKeyDown(KeyCode.S))
{
_direction = Vector2.down; Flip();
}
else if (Input.GetKeyDown(KeyCode.D))
{
_direction = Vector2.right; Flip();
}
else if (Input.GetKeyDown(KeyCode.A))
{
_direction = Vector2.left; Flip();
}
}
private void FixedUpdate()
{
this.transform.position = new Vector3(
Mathf.Round(this.transform.position.x) + _direction.x,
Mathf.Round(this.transform.position.y) + _direction.y,
0.0f);
}
void Flip()
{
Vector3 currentScale = gameObject.transform.localScale;
currentScale.x *= -1;
gameObject.transform.localScale = currentScale;
facingRight = !facingRight;
}
}
I'm trying to make an google snake like game and I got the movement all right but it doesn't flip up and down. If I click A and D on my keyboard it flips left and right, but if I click W or S it flips left or right for some reason.
Here is my code:
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class snakemovement : MonoBehaviour
{
private Vector2 _direction = Vector2.right; bool facingRight = true;
void Update()
{
if (Input.GetKeyDown(KeyCode.W))
{
_direction = Vector2.up; Flip();
}
else if (Input.GetKeyDown(KeyCode.S))
{
_direction = Vector2.down; Flip();
}
else if (Input.GetKeyDown(KeyCode.D))
{
_direction = Vector2.right; Flip();
}
else if (Input.GetKeyDown(KeyCode.A))
{
_direction = Vector2.left; Flip();
}
}
private void FixedUpdate()
{
this.transform.position = new Vector3(
Mathf.Round(this.transform.position.x) + _direction.x,
Mathf.Round(this.transform.position.y) + _direction.y,
0.0f);
}
void Flip()
{
Vector3 currentScale = gameObject.transform.localScale;
currentScale.x *= -1;
gameObject.transform.localScale = currentScale;
facingRight = !facingRight;
}
}
Share
Improve this question
edited 2 days ago
marc_s
755k184 gold badges1.4k silver badges1.5k bronze badges
asked 2 days ago
Mr penguinMr penguin
193 bronze badges
New contributor
Mr penguin is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
1
|
3 Answers
Reset to default 1Also if you press D key various times the character will flip left and right even if still advancing on the same direction.
You should add to flip a parameter, for example a Vector2 one with the desired directions of the flip instead of using an alternating strategy.
Define Flip as this:
void Flip(Vector2 direction)
{
Vector3 currentScale = gameObject.transform.localScale;
if (direction.x != 0f) currentScale.x *= direction.x;
if (direction.y != 0f) currentScale.y *= direction.y;
gameObject.transform.localScale = currentScale;
}
Call to Flip with:
Flip(_direction);
The facingRight variable is useless as you use it. Also you should perform all in Update instead of using FixedUpdate because you are not using physics there. And whistl you will get a variable-velocity moving character you should multiply by Time.deltaTime instead.
Your Flip
method seems to mirror the character across the y axis if I understand it correctly. Since you are calling the Flip
method every time the W
or S
key gets pressed, the character will be mirrored across the y axis (flip left or right) every time one of those keys gets pressed.
I am not very experienced with Unity but based on your code I assume that you can set gameObject.transform.localScale.y
to -gameObject.transform.localScale.y
to mirror the character across the x axis.
So to fix your problem you should rename your Flip
method to FlipHorizontal
and create a new method called FlipVertical
. The FlipVertical
method could look something like this:
private void FlipVertical()
{
Vector3 currentScale = gameObject.transform.localScale;
currentScale.y *= -1;
gameObject.transform.localScale = currentScale;
}
I would also suggest not making the method toggle the orientation of the character but instead setting it based on a parameter to make the code more readable and reliable.
private enum Orientation
{
Left,
Right,
Up,
Down
}
private void SetOrientation(Orientation orientation)
{
Vector3 currentScale = gameObject.transform.localScale;
switch(orientation)
{
case Orientation.Left or Orientation.Right:
currentScale.x = Orientation.Right ? 1 : -1; // Multiply by a size variable if you want to change the size of your character
break;
case Orientation.Up or Orientation.Down:
currentScale.y = Orientation.Up ? 1 : -1;
break;
default:
break;
}
gameObject.transform.localScale = currentScale;
}
And then just call the method like this
SetOrientation(Orientation.Right); // Or any other orientation
Your function is missing how to handle the vertical y
axis, as pointed in the comments; other that it's just flipping without checking if it's already on the right direction.
You can use one of multiple approaches, like passing to Flip()
a key value to handle each axis like:
void Update()
{
if (Input.GetKeyDown(KeyCode.W))
{
_direction = Vector2.up; Flip(KeyCode.W);
}
else if (Input.GetKeyDown(KeyCode.S))
{
_direction = Vector2.down; Flip(KeyCode.S);
}
else if (Input.GetKeyDown(KeyCode.D))
{
_direction = Vector2.right; Flip(KeyCode.D);
}
else if (Input.GetKeyDown(KeyCode.A))
{
_direction = Vector2.left; Flip(KeyCode.A);
}
}
void Flip(key)
{
switch (key)
{
case KeyCode.W:
if (!facingUp) {
Vector3 currentScale = gameObject.transform.localScale;
currentScale.y *= -1;
gameObject.transform.localScale = currentScale;
facingUp = true;
}
break;
case KeyCode.A:
if (facingRight) {
Vector3 currentScale = gameObject.transform.localScale;
currentScale.x *= -1;
gameObject.transform.localScale = currentScale;
facingRight = false;
}
break;
case KeyCode.S:
if (facingUp) {
Vector3 currentScale = gameObject.transform.localScale;
currentScale.y *= -1;
gameObject.transform.localScale = currentScale;
facingUp = false;
}
break;
case KeyCode.D:
if (!facingRight) {
Vector3 currentScale = gameObject.transform.localScale;
currentScale.x *= -1;
gameObject.transform.localScale = currentScale;
facingRight = true;
}
break;
default:
break;
}
}
Another option is to split Flip
into two separate functions, say, FlipVertically()
and FlipHorizontally()
. Something along these lines:
void Update()
{
if (Input.GetKeyDown(KeyCode.W))
{
_direction = Vector2.up; FlipVertically();
}
else if (Input.GetKeyDown(KeyCode.S))
{
_direction = Vector2.down; FlipVertically();
}
else if (Input.GetKeyDown(KeyCode.D))
{
_direction = Vector2.right; FlipHorizontally();
}
else if (Input.GetKeyDown(KeyCode.A))
{
_direction = Vector2.left; FlipHorizontally();
}
}
void FlipHorizontally()
{
Vector3 currentScale = gameObject.transform.localScale;
currentScale.x *= -1;
gameObject.transform.localScale = currentScale;
facingRight = !facingRight;
}
void FlipVertically()
{
Vector3 currentScale = gameObject.transform.localScale;
currentScale.y *= -1;
gameObject.transform.localScale = currentScale;
facingUp = !facingUp;
}
Ultimately the choice is yours, but remember to include another bool
if you need to store the facing of your character or better, try to save its state in an enum
. That can be simple as
enum direction
{
UP,
DOWN,
LEFT,
RIGHT
}
and you replace the various bool
s with it
currentScale.y
is missing in the Flip() function? – Luuk Commented 2 days ago