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:
- The target grid position is calculated based on the current player position (
rb.position
) divided by thegridSize
. This gives the grid cell that the player is currently in.- The center of the next tile in the movement direction is calculated by adding the
movementInput
vector to the target grid position.- The
rb.MovePosition
method is then used to smoothly move the player towards the calculated center of the next tile. It usesVector2.Lerp
to interpolate between the current position and the target position.nextTileCenter * gridSize
converts the grid position back to world space.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