Reputation: 455
I'm making a turn-based top-down 2D dungeon crawler in Unity with C#. I'm currently programming the code for the bat enemy to follow the player. It's working well except for one weird behavior. The bat moves in 2 directions by 2 blocks instead of in 1 direction by 1 block, but only for it's first movement. Similar to the movement the knight makes in chess. Please help me figure this out. Any and all suggestions appreciated. My code is probably awful and overly complicated, but this is my first game so please be gentle.
Enemy code:
Vector3 currentPosition;
Vector3 nextPosition;
public GameObject playerObject;
public Transform[] wallArray;
bool canMove;
public Player thePlayer;
void Update()
{
currentPosition = transform.position;
Movement();
}
void Movement()
{
if (thePlayer.timeToMove == false)
{
if (playerObject.transform.position.x > currentPosition.x)
{
nextPosition.x = currentPosition.x + 1;
canMove = false;
foreach (Transform wall in wallArray)
{
if (wall.transform.position.Equals(nextPosition))
{
nextPosition = currentPosition;
canMove = true;
}
}
if (canMove)
{
if (playerObject.transform.position.y > currentPosition.y)
{
nextPosition.y = currentPosition.y + 1;
foreach (Transform wall in wallArray)
{
if (wall.transform.position.Equals(nextPosition))
{
nextPosition = currentPosition;
}
}
}
if (playerObject.transform.position.y < currentPosition.y)
{
nextPosition.y = currentPosition.y - 1;
foreach (Transform wall in wallArray)
{
if (wall.transform.position.Equals(nextPosition))
{
nextPosition = currentPosition;
}
}
}
}
if (nextPosition == playerObject.transform.position)
{
nextPosition = currentPosition;
}
transform.position = nextPosition;
thePlayer.timeToMove = true;
Debug.Log("Leaving 'a'...");
return;
}
if (playerObject.transform.position.x < currentPosition.x)
{
nextPosition.x = currentPosition.x - 1;
canMove = false;
foreach (Transform wall in wallArray)
{
if (wall.transform.position.Equals(nextPosition))
{
nextPosition = currentPosition;
canMove = true;
}
}
if (canMove)
{
if (playerObject.transform.position.y > currentPosition.y)
{
nextPosition.y = currentPosition.y + 1;
foreach (Transform wall in wallArray)
{
if (wall.transform.position.Equals(nextPosition))
{
nextPosition = currentPosition;
}
}
}
if (playerObject.transform.position.y < currentPosition.y)
{
nextPosition.y = currentPosition.y - 1;
foreach (Transform wall in wallArray)
{
if (wall.transform.position.Equals(nextPosition))
{
nextPosition = currentPosition;
}
}
}
}
if (nextPosition == playerObject.transform.position)
{
nextPosition = currentPosition;
}
transform.position = nextPosition;
thePlayer.timeToMove = true;
Debug.Log("Leaving 'b'...");
return;
}
if (playerObject.transform.position.x == currentPosition.x)
{
if (playerObject.transform.position.y > currentPosition.y)
{
nextPosition.y = currentPosition.y + 1;
foreach (Transform wall in wallArray)
{
if (wall.transform.position.Equals(nextPosition))
{
nextPosition = currentPosition;
}
}
}
if (playerObject.transform.position.y < currentPosition.y)
{
nextPosition.y = currentPosition.y - 1;
foreach (Transform wall in wallArray)
{
if (wall.transform.position.Equals(nextPosition))
{
nextPosition = currentPosition;
}
}
}
if (nextPosition == playerObject.transform.position)
{
nextPosition = currentPosition;
}
transform.position = nextPosition;
thePlayer.timeToMove = true;
Debug.Log("Leaving 'c'...");
return;
}
}
Player code:
// Movement variables
public Vector3 playerCurrentPosition;
Vector3 nextPosition;
public Transform[] wallArray;
public bool timeToMove;
bool movingToWall;
void Start()
{
// When we start we can move
timeToMove = true;
}
void Update()
{
// Update current position variable
playerCurrentPosition = transform.position;
// Move
Movement();
}
// Movement
void Movement()
{
// If it's time to move
if (timeToMove)
{
// If right arrow key pressed
if (Input.GetKeyDown(KeyCode.RightArrow))
{
// Set position to move to
nextPosition.x = playerCurrentPosition.x + 1;
// Check wall array
foreach (Transform wall in wallArray)
{
// If the wall we are checking is in the space we want to move to
if (wall.transform.position.Equals(nextPosition))
{
// We are moving into a wall
movingToWall = true;
}
}
// If we are moving into a wall
if (movingToWall)
{
// Don't move
nextPosition = playerCurrentPosition;
// Set position
transform.position = nextPosition;
// It's time to move again
timeToMove = true;
// We're not moving into a wall anymore
movingToWall = false;
}
// If we're not moving into a wall
else
{
// Move
transform.position = nextPosition;
// It's no longer time to move
timeToMove = false;
}
}
// If left arrow key pressed
if (Input.GetKeyDown(KeyCode.LeftArrow))
{
// Set position we want to move to
nextPosition.x = playerCurrentPosition.x - 1;
// Check wall array
foreach (Transform wall in wallArray)
{
// If the wall we are checking is in the space we want to move to
if (wall.transform.position.Equals(nextPosition))
{
// We are moving into a wall
movingToWall = true;
}
}
// If we are moving into a wall
if (movingToWall)
{
// Don't move
nextPosition = playerCurrentPosition;
// Set position
transform.position = nextPosition;
// We can move again
timeToMove = true;
// We are no longer moving into a wall
movingToWall = false;
}
// If we are not moving into a wall
else
{
// Move
transform.position = nextPosition;
// It is no longer time to move
timeToMove = false;
}
}
// If up arrow pressed
if (Input.GetKeyDown(KeyCode.UpArrow))
{
// Set position to move to
nextPosition.y = playerCurrentPosition.y + 1;
// Check wall array
foreach (Transform wall in wallArray)
{
// If wall we are checking is in space we want to move to
if (wall.transform.position.Equals(nextPosition))
{
// We are moving into a wall
movingToWall = true;
}
}
// If we are moving into a wall
if (movingToWall)
{
// Don't move
nextPosition = playerCurrentPosition;
// Set position
transform.position = nextPosition;
// We can move again
timeToMove = true;
// No longer moving into wall
movingToWall = false;
}
// If we are not moving into a wall
else
{
// Move
transform.position = nextPosition;
// It is no longer time to move
timeToMove = false;
}
}
// If down arrow pressed
if (Input.GetKeyDown(KeyCode.DownArrow))
{
// Set position to move to
nextPosition.y = playerCurrentPosition.y - 1;
// Check wall array
foreach (Transform wall in wallArray)
{
// If wall we are checking is in the space we want to move to
if (wall.transform.position.Equals(nextPosition))
{
// We are moving into a wall
movingToWall = true;
}
}
// If we are moving into a wall
if (movingToWall)
{
// Don't move
nextPosition = playerCurrentPosition;
// Set position
transform.position = nextPosition;
// We can move again
timeToMove = true;
// No longer moving into a wall
movingToWall = false;
}
// If we are not moving into a wall
else
{
// Move
transform.position = nextPosition;
// No longer time to move
timeToMove = false;
}
}
}
}
Upvotes: 0
Views: 115
Reputation: 12582
Is there a chance that your problem is, you should be using breakaway code and you are not? Your code is like this:
void Movement()
{
if (Player.timeToMove == false)
{
if (playerObject.transform.position.x > currentPosition.x)
{
// huge amount of code
}
if (playerObject.transform.position.x < currentPosition.x)
{
// huge amount of code
}
if (playerObject.transform.position.x == currentPosition.x)
{
// huge amount of code
}
}
}
In fact, should it be like this ?
void Movement()
{
if (Player.timeToMove == false)
{
if (playerObject.transform.position.x > currentPosition.x)
{
// huge amount of code
Debug.Log("Leaving 'a'...");
return;
}
if (playerObject.transform.position.x < currentPosition.x)
{
// huge amount of code
Debug.Log("Leaving 'b'...");
return;
}
if (playerObject.transform.position.x == currentPosition.x)
{
// huge amount of code
Debug.Log("Leaving 'c'...");
return;
}
}
}
I suggest trying that.
Note, you truly need to introduce some functions to simplify your code. Your code passage like this ...
foreach (Transform wall in wallArray)
if (wall.transform.position.Equals(nextPosition))
{
movingToWall = true;
}
should be a function more like this:
private bool IsThisAWall(Vector3 p)
{
foreach (Transform wall in wallArray)
if (wall.transform.position.Equals(p))
{
return true;
}
return false;
}
you would then use it sort of like this. you'd have a variable "possibleNewPosition". you'd say ...
possibleNewPosition = currentPosition + 1; if ( IsThisAWall(possibleNewPosition) ) Debug.Log("doing nothing since it's a wall"); else currentPosition = possibleNewPosition;
It's very common that you do that, you have a variable "possible ..." something or other!
You really need to do this in time. (Don't forget in programming, no routine should ever be longer than say 5 or 6 lines of code. Your Movement
etc calls are tremendously too long.)
Upvotes: 3