can't get transform.translate to work properly

So, I’ve been making a turn based dungeon game, and trying to get the player to move properly based off of turn based movement has proven to be very difficult, here’s my script

using UnityEngine;
using System.Collections;

public class PlayerMovement : MonoBehaviour
{
    private bool IsMoving = false;

    public Animator animator;

    private bool flipped = false;

    private Vector3 positionStore = Vector3.zero;

    IEnumerator PlayerMoveUp()
    {
        IsMoving = true;

        yield return new WaitForSeconds(0.15f);

        IsMoving = false;
    }

    IEnumerator PlayerMoveDown()
    {
        IsMoving = true;

        yield return new WaitForSeconds(0.15f);

        IsMoving = false;
    }

    IEnumerator PlayerMoveRight()
    {
        IsMoving = true;

        yield return new WaitForSeconds(0.15f);

        IsMoving = false;
    }

    IEnumerator PlayerMoveLeft()
    {
        IsMoving = true;

        yield return new WaitForSeconds(0.15f);

        IsMoving = false;
    }

    private void Update()
    {
        if (!IsMoving)
        {
            if (Input.GetKey(KeyCode.UpArrow))
            {
                animator.SetBool("IsFacingForwards", false);
                animator.SetBool("IsFacingSide", false);
                animator.SetBool("IsFacingBackwards", true);

                StartCoroutine(PlayerMoveUp());
                transform.Translate(Vector2.up);

            } else if (Input.GetKey(KeyCode.DownArrow))
            {
                animator.SetBool("IsFacingForwards", true);
                animator.SetBool("IsFacingSide", false);
                animator.SetBool("IsFacingBackwards", false);

                StartCoroutine(PlayerMoveDown());
                transform.Translate(Vector2.down);

            } else if (Input.GetKey(KeyCode.RightArrow))
            {
                if (flipped)
                {
                    transform.Rotate(0, 180, 0);
                }

                animator.SetBool("IsFacingForwards", false);
                animator.SetBool("IsFacingSide", true);
                animator.SetBool("IsFacingBackwards", false);

                StartCoroutine(PlayerMoveRight());
                transform.Translate(Vector2.right);

            } else if (Input.GetKey(KeyCode.LeftArrow))
            {
                if (!flipped)
                {
                    transform.Rotate(0, 0, 0);
                }

                animator.SetBool("IsFacingForwards", false);
                animator.SetBool("IsFacingSide", true);
                animator.SetBool("IsFacingBackwards", false);

                StartCoroutine(PlayerMoveLeft());
                transform.Translate(Vector2.left);
            }
        }
    }
}

right now the script will teleport the player to the position I want them to go, rather than moving them normally (I already know why that’s part’s happening, I just mentioned it because I can’t figure how to write normal movement, but still get it to work turn based), although, the part I can’t figure out, is that the player is supposed to change their animation when they move, so for example, if the player is facing upwards, and I move them to the side, they should immediately change to the side animation, but it will wait 0.15 seconds rather than being immediate, which is weird because I didn’t put the code in the cororoutine, does anyone know how to write this script correctly?

Also, thanks in advance to anyone who helps

Definitely no call for coroutines. That’s just a needless complication.

I would use this pattern:

Smoothing movement between any two particular values:

You have currentQuantity and desiredQuantity.

  • only set desiredQuantity
  • the code always moves currentQuantity towards desiredQuantity
  • read currentQuantity for the smoothed value

Works for floats, Vectors, Colors, Quaternions, anything continuous or lerp-able.

The code: SmoothMovement.cs · GitHub

BASED on the above,

  • Have one set of current/desired values for rotation (use MoveTowardsAngle() ) and one set for position.

  • when you detect input, set only desired rotation and position

  • drive the current rotation and position to the visible transform.

As long as current position is more than a tiny smidge away from desired position, inhibit all input.

Went digging in my old board game repo, dug up some relevant code, stuck it in a scene. See attached.

Relevant code (all set up in attached package):

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

public class FourDirectionalTurnBased : MonoBehaviour
{
    [Header( "Either supply or we GetComponent<T>();")]
    public Transform PlayerTransform;

    Vector3 currentPosition;
    Vector3 desiredPosition;

    float currentRotation;
    float desiredRotation;

    float CellSize = 1.0f;
    float MoveSpeed = 5.0f;
    float RotationSpeed = 1200.0f;

    void Start()
    {
        if (!PlayerTransform)
        {
            PlayerTransform = transform;
        }

        // start facing the player
        desiredRotation = 180;
        currentRotation = desiredRotation;
    }

    bool Moving()
    {
        // move
        currentPosition = Vector3.MoveTowards( currentPosition, desiredPosition, MoveSpeed * Time.deltaTime);

        // rotate
        currentRotation = Mathf.MoveTowardsAngle( currentRotation, desiredRotation, RotationSpeed * Time.deltaTime);

        // done?
        Vector3 d = currentPosition - desiredPosition;
        return d.magnitude > 0.01f;
    }

    void DriveTransform()
    {
        PlayerTransform.rotation = Quaternion.Euler( 0, currentRotation, 0);
        PlayerTransform.position = currentPosition;
    }

    void ReadInput()
    {
        var x = Input.GetAxisRaw("Horizontal");
        var y = Input.GetAxisRaw("Vertical");

        if (x < -0.5f)
        {
            desiredRotation = -90;
            desiredPosition += Vector3.left * CellSize;
        }
        if (x > 0.5f)
        {
            desiredRotation = 90;
            desiredPosition += Vector3.right * CellSize;
        }
        if (y > 0.5f)
        {
            desiredRotation = 0;
            desiredPosition += Vector3.forward * CellSize;
        }
        if (y < -0.5f)
        {
            desiredRotation = 180;
            desiredPosition += Vector3.back * CellSize;
        }
    }

    void Update ()
    {
        if (!Moving())
        {
            ReadInput();
        }

        DriveTransform();
    }
}

If you’re interested in dungeon crawler stuff, check this guy’s writings out:

https://journal.stuffwithstuff.com/category/roguelike/

7512452–926297–FourDirectionalTurnBased.unitypackage (301 KB)

Wow, thank you for all the help with everything, I really didn’t expect you to go above and beyond with assistance like that, and you’re also the person who helped me fix my last issue, so I just want to say thank you so much for helping me

1 Like