How do I store an object's position from the previous frame?

Hello, I have been trying to figure out why this code isn’t working like I thought. The “lastPosition” variable is always the same as the “currentPosition” variable, although I thought I cached the transform.position on the current frame within the “currentPosition” variable. I feel like it’s a very simple error, but I’m not sure where. Here is my code:

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

public class PlayerMovement : MonoBehaviour
{
    [SerializeField]
    private float moveSpeed = 2f;

    [SerializeField]
    private float currentSpeed;

    private Vector3 lastPosition;


    [SerializeField]
    private float strengthMultiplier;

    [SerializeField]
    private float strengthDiminisher = 7000f;

    private bool isRollingForwards;

    private bool isRollingBackwards;

    private bool isRollingLeft;

    private bool isRollingRight;


    private void Start()
    {
        lastPosition = transform.position;
    }

    private void Update()
    {
        Vector2 inputVector = new Vector2(0, 0);

        Vector3 currentPosition = transform.position;


        currentSpeed = (currentPosition - lastPosition).magnitude / Time.deltaTime;


        strengthMultiplier = currentSpeed / strengthDiminisher;

        if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
        {
            inputVector.y = +1;
        }

        if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow))
        {
            inputVector.y = -1;
        }

        if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
        {
            inputVector.x = -1;
        }

        if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
        {
            inputVector.x = +1;
        }

       
        inputVector = inputVector.normalized;

        Vector3 moveDir = new Vector3(inputVector.x, 0f, inputVector.y);

        Vector3 playerVelocity = (currentPosition - lastPosition) / Time.deltaTime;

        Vector3 playerDir = playerVelocity.normalized;

      

        isRollingForwards =  currentPosition.z > lastPosition.z;

        isRollingBackwards = transform.rotation.x < 0f;

        isRollingLeft = transform.rotation.z > 0f;

        isRollingRight = transform.rotation.z < 0f;


        transform.position += moveDir * moveSpeed * strengthMultiplier * Time.deltaTime;
       

        lastPosition = transform.position;

    }

    public bool IsRollingForwards()
    {
        return isRollingForwards;
    }

    public bool IsRollingBackwards()
    {
        return isRollingBackwards;
    }

    public bool IsRollingLeft()
    {
        return isRollingLeft;
    }

    public bool IsRollingRight()
    {
        return isRollingRight;
    }
}

It’s because you’re caching lastPosition AFTER updating transform.position to the new position!
Swap lines 88 and 91.

I tried this, but it did not work. I took my original code and added a Debug.Log for each of the variables: lastPosition, currentPosition, and transform.position. Each value was exactly the same, no matter how much the object moves.

I also tried to make your change and then add the Debug.Log statements again, but it’s still the same unchanging value on all 3 variables.

        lastPosition = currentPosition;
        transform.position += moveDir * moveSpeed * strengthMultiplier * Time.deltaTime;
        Debug.Log($"moveDir={moveDir} | moveSpeed={moveSpeed:F4} | strength={strengthMultiplier:F4} | deltaTime={Time.deltaTime:F6}";

Try debugging like so. See what’s zero.

The moveDir and strengthMultiplier are always 0. This is because the way I calculate it depends on subtracting the lastPosition from the currentPosition.

I did notice that the regular transform.position isn’t actually updating in the inspector. It’s showing the same starting position values for lastPosition, currentPosition, and transform.position without updating. I have never seen that happen before and I’m not sure why that is the case, since the object is clearly moving in world space in the scene view when I look at the gizmo for it.

So if you’re not moving, you can never begin moving:

        strengthMultiplier = currentSpeed / strengthDiminisher;

If current speed is zero, then strengthMultiplier will become zero, so

 transform.position += moveDir * moveSpeed * strengthMultiplier * Time.deltaTime;

will always add zero.

Yes, this is what I said in my previous post. I was just confused as to why lastPosition, currentPosition, and transform.position all remain the same starting value. If this is solved, then the rest of my equations should work since those values won’t be (0,0,0).

I quickly searched as to why this may be happening, and it seems to be due to the fact that I have the script attached to the parent object which has a child object with the visuals but also contains a rigidbody component. Since child objects can’t move parent objects, the appearance of the parent object moving in the scene is just the way Unity displays it.

The reason I set it up this way is because I was told to always keep the logic separate from the visuals, but also my object is a ball and I want a 3rd person camera to follow behind. So basing the camera’s position and rotation on the ball itself causes the camera to orbit the ball as it rolls, instead of being at a locked distance and angle.

Well, in Start() you set lastPosition equal to transform.position. So currentPosition-lastPosition will be zero right away. But because of strengthMultiplier you won’t be able to escape zero. And if you stop moving, you’ll have the same problem anyway. You have to eliminate your strengthMultiplier and accomplish the same some other way. The point of strengthMultiplier is to add some smoothing? Try Vector3.SmoothDamp for example.

If this is a physics object, though, it should be moved via its rigidbody, like AddForce