简体   繁体   中英

Weird movement behaviour Unity2D C#

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;
            }
        }
    }       
}

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.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM