Grid based movement in isometric 3D environment

I’m trying to script a grid movement system that functions properly in an isometric environment I’ve set up. I’m designing a block pushing puzzle game, sort of in the vein of Sokoban.

I can already move, but the script I’ve set up for it does some wonky stuff with the inputs to make it play nice with an isometric camera. I’ve looked up a few tutorials, but I’m having trouble figuring out how to make them work with my existing code. Any advice?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    [SerializeField]
    float moveSpeed = 4.0f;

    Vector3 forward, right;

    // Start is called before the first frame update
    void Start()
    {
        //our forward vector is equal to the camera's forward vector in local space
        forward = Camera.main.transform.forward;
        forward.y = 0;
        forward = Vector3.Normalize(forward);
        right = Quaternion.Euler(new Vector3(0, 90, 0)) * forward;
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.anyKey)
        {
            Move();
        }
    }

    void Move()
    {
        //Our new direction is equal to the input along the x and y axes at any given time
        Vector3 direction = new Vector3(Input.GetAxis("VerticalKey"), 0, Input.GetAxis("HorizontalKey"));
        Vector3 rightMovement = right * moveSpeed * Time.deltaTime * Input.GetAxis("HorizontalKey");
        Vector3 upMovement = forward * moveSpeed * Time.deltaTime * Input.GetAxis("VerticalKey");

       
        Vector3 heading = Vector3.Normalize(rightMovement + upMovement);

        transform.forward = heading;

        //Causes Movement
        transform.position += rightMovement;
        transform.position += upMovement;
    }
}

What isn’t working?

Sorry, should have clarified, I’m trying to set up a system where I move by increments, sliding a unit at a time. My current system isn’t that, just “standard” fluid movement.

You’ll want two main things to get this working:

  • A way to keep track of your player’s current grid-space coordinates
  • A way to map grid-space to 3D space (and back)

Then all you have to do is, based on the input, calculate the neighboring grid space you want the character to move to. Then you just Lerp the character from their current position to the world space position that represents that grid-space position.

Psuedocode:

Vector2Int moveDirection;

if (pressedLeftButton) {
  moveDirection = Vector2Int.left;
}
// etc. for other directions.

Vector2Int currentPosition = // current player grid position
Vector2Int newPosition = currentPosition + moveDirection;

// Calculate the world position for that grid position
Vector3 targetWorldPosition = GetWorldPositionForGridPosition(newPosition);

// Start moving
StartCoroutine(MoveCoroutine(player.transform, targetWorldPosition));

The movement coroutine could be pretty simple:

IEnumerator MoveCoroutine(Transform player, Vector3 targetPosition) {
  while (Vector3.Distance(player.position, targetPosition) > .001f) {
    player.position = Vector3.MoveTowards(player.position, targetPosition, Time.deltaTime * MoveSpeed);
    yield return null;
  }
}
1 Like

@es

Were you able to figure this out? I could use the help figuring this out. I’m struggling to understand PraetorBlue’s explanation