Issues with implementing tile-snap movement system

Hello,

I’m working on incorporating tile-based movement for my character, aiming to have the character aligned with the next tile in the direction of movement. Currently, there’s an issue where the player is consistently snapped to the top and right cells, irrespective of the input directions. As a consequence, when I move the character left or bottom, it snaps to the right or upper cell, rather than the next one in the intended direction. I’m utilizing the new player input system.

Current logic:

  1. The target grid position is calculated based on the current player position (rb.position) divided by the gridSize. This gives the grid cell that the player is currently in.
  2. The center of the next tile in the movement direction is calculated by adding the movementInput vector to the target grid position.
  3. The rb.MovePosition method is then used to smoothly move the player towards the calculated center of the next tile. It uses Vector2.Lerp to interpolate between the current position and the target position.
  4. nextTileCenter * gridSize converts the grid position back to world space.
  5. new Vector2(gridSize / 2, gridSize / 2) is added to ensure that the player moves to the center of the next tile.

script:

using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerController : MonoBehaviour
{
    public float moveSpeed = 1f;
    public float snapSpeed = 10.0f;
    public LayerMask collisionLayer;

    Vector2 movementInput;
    SpriteRenderer spriteRenderer;
    Rigidbody2D rb;
    Animator animator;
    Transform gridTransform; // Reference to the grid game object

    bool canMove = true;
    float gridSize = 0.16f;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        animator = GetComponent<Animator>();
        spriteRenderer = GetComponent<SpriteRenderer>();

        // Find the grid game object
        gridTransform = GameObject.Find("Grid").transform;
    }

    private void FixedUpdate()
    {
    if (canMove)
    {
        // Get raw input without normalization
        Vector2 rawInput = movementInput;

        // Normalize the input vector to limit diagonal movement
        movementInput = new Vector2(Mathf.Round(rawInput.x), Mathf.Round(rawInput.y)).normalized;

        if (movementInput != Vector2.zero)
        {
            // Calculate the target position on the grid
            Vector2 targetPosition = CalculateTargetPosition(rb.position, movementInput);

            // Check for potential collisions
            RaycastHit2D hit = Physics2D.Raycast(targetPosition, Vector2.zero, gridSize, collisionLayer);
            if (hit.collider == null)
            {
                // Move towards the target position using Rigidbody2D.MovePosition()
                rb.MovePosition(rb.position + movementInput * moveSpeed * Time.deltaTime);
            }
            else
            {
                // Player hit something, try to snap to the grid smoothly
                SmoothSnapToGrid();
            }

            animator.SetBool("isMoving", true);
        }
        else
        {
            // Player is not moving, try to snap to the grid smoothly
            SmoothSnapToGrid();

            animator.SetBool("isMoving", false);
        }

        // Set direction of sprite to movement direction
        if (movementInput.x < 0)
        {
            spriteRenderer.flipX = true;
        }
        else if (movementInput.x > 0)
        {
            spriteRenderer.flipX = false;
        }
    }
}

    private void SmoothSnapToGrid()
    {
        // Calculate the target grid position
        Vector2 targetGridPosition = new Vector2(
            Mathf.Round(rb.position.x / gridSize),
            Mathf.Round(rb.position.y / gridSize)
        );

        // Calculate the center of the next tile in the movement direction
        Vector2 nextTileCenter = targetGridPosition + movementInput;

        // Smoothly move towards the center of the next tile in the movement direction
        rb.MovePosition(Vector2.Lerp(rb.position, nextTileCenter * gridSize + new Vector2(gridSize / 2, gridSize / 2), snapSpeed * Time.deltaTime));
    }

    private Vector2 CalculateTargetPosition(Vector2 currentPosition, Vector2 direction)
    {
        // Calculate the target position based on the movement direction
        Vector2 targetPosition = currentPosition + direction * moveSpeed * Time.deltaTime;

        return targetPosition;
    }

    void OnMove(InputValue movementValue)
{
    Vector2 rawInput = movementValue.Get<Vector2>();
    float horizontal = Mathf.Round(rawInput.x);
    float vertical = Mathf.Round(rawInput.y);

    // Ensure only one direction is considered
    if (Mathf.Abs(horizontal) > Mathf.Abs(vertical))
    {
        movementInput = new Vector2(horizontal, 0f).normalized;
    }
    else
    {
        movementInput = new Vector2(0f, vertical).normalized;
    }
}


    public void LockMovement()
    {
        canMove = false;
    }

    public void UnlockMovement()
    {
        canMove = true;
    }
}

Anyone could help with that please?
Thank you

fixed by changing SmoothSnapToGrid function.
Instead of rounding, using Mathf.Ceil and Mathf.Floor:

private void SmoothSnapToGrid()
{
    // Calculate the target grid position
    Vector2 targetGridPosition = new Vector2(
        (movementInput.x < 0) ? Mathf.Ceil(rb.position.x / gridSize) : Mathf.Floor(rb.position.x / gridSize),
        (movementInput.y < 0) ? Mathf.Ceil(rb.position.y / gridSize) : Mathf.Floor(rb.position.y / gridSize)
    );

    // Calculate the center of the next tile in the movement direction
    Vector2 nextTileCenter = targetGridPosition + movementInput;

    // Smoothly move towards the center of the next tile in the movement direction
    rb.MovePosition(Vector2.Lerp(rb.position, nextTileCenter * gridSize + new Vector2(gridSize / 2, gridSize / 2), snapSpeed * Time.deltaTime));
}

    private Vector2 CalculateTargetPosition(Vector2 currentPosition, Vector2 direction)
    {
        // Calculate the target position based on the movement direction
        Vector2 targetPosition = currentPosition + direction * moveSpeed * Time.deltaTime;

        return targetPosition;
    }