My follow Player script is not smooth.

I need help to understand why my Follower script, that acts like a replay system (this is needed), looks like it is shaking / stuttering / jittering and if there is any way of fixing it using the method of recording the Player’s positions and repeating them?

In the editor I skip from one frame to the next frame and can see my 2D Player running / moving (2D platformer), but my Follower moves one frame, waits the next frame, then updates to the next recorded frame of the Player’s past movement / position.

I’ve looked up examples of coding the tail/body in the game Snake, replay system for games, and other similar examples of repeating the player’s position at a distance, but can not see a solution for smoothing past recorded positions in real time. I even looked up exactly what it is I am trying to create which is a sidekick / follower / companion / helper. So far I am the closest one that has code to share how to create this. I’m aware of using Vector3.Lerp but I keep getting my follower to float around instead of touching the ground when repeating a jump. Makes the follower look like the can fly which is not true in my project.

Anyone able to glance at the code and see a possible fix?

Here is the code (TargetFollower.cs) EDIT The code is now less jittery when pushed to mobile. It still will jitter randomly, but it is completely smooth otherwise. In Unity’s editor the follower is less shaky, but skips forward instead of Lerping smoothly. Still working on it. Will re-edit when completely fixed so others can learn from it if needed :

using UnityEngine;
using System.Collections;
using System;

public class TargetFollower : MonoBehaviour
{
    public Transform target = null;                    // follow by target
    public float reactDelay = 0.1f;                    // how fast it react to target moves
    public float recordFPS = 60f;                    // how many record data in one second 
    public float followSpeed = 5f;                    // follow speed
    public float targetDistance = 0.5f;                // don't move closer than this value
    public bool targetDistanceY = true;            // if near then update y only
    public bool start = true;                        // start or stop follow    

    [Serializable] //Shows in inspector
    public class TargetRecord
    {
        public Vector3 position;                    // world position
        public TargetRecord(Vector3 position)
        {
            this.position = position;
        }
    }

    public TargetRecord[] _records = null;          // keeps target data in time // type[] nameOfArray = lengthOfArray
    private float _t = 0f;
    private int _i = 0;                             // keeps current index for recorder
    private int _j = 1;                             // keeps current index for follower
    private float _interval = 0f;
    private TargetRecord _record = null;            // current record
    private bool _recording = true;                 // stop recording if true
    private int _arraySize = 1;

    public void Start()
    {
        Initialize();
    }

    public void Initialize()
    {
        _interval = 1 / recordFPS;

        _arraySize = Mathf.CeilToInt(recordFPS * reactDelay);
        if (_arraySize == 0)
            _arraySize = 1;

        _records = new TargetRecord[_arraySize];
    }

    // update this transform data
    public void Update()
    {
        if (start)
        whe{
            // can be move into the Update or LateUpdate if needed
            RecordData(Time.deltaTime);

            // move to the target
            if (targetDistance <= 0f)
            {
                if (_record != null)
                    transform.position = Vector3.Lerp(_records[_i].position, _records[_j].position, Time.deltaTime * 5);
            }
            else if ((target.position - transform.position).magnitude > targetDistance)
            {
                if (!_recording)
                {
                    ResetRecordArray();
                    _recording = true;
                }

                if (_record != null)
                    transform.position = Vector3.Lerp(_records[_i].position, _records[_j].position, Time.deltaTime); //Player is moving and they're position is being recorded. The follower then moves to the 
                    //Debug.Log("1 - _records[_jiposition = " + _records[_i].position);
                    //Debug.Log("2 - _records[_j].position = " + _records[_j].position);
            }
            else if (targetDistanceY && Mathf.Abs(target.position.y - transform.position.y) > targetDistance)
            {
                if (_record != null)
                    transform.position = Vector3.Lerp(transform.position, new Vector3(transform.position.x, target.position.y, transform.position.z), Time.deltaTime * followSpeed); //The follower is adjusting its Y axis because the Player is close and not moving.
            }
            //else
            //{
            //    _recording = false; //The player is not moving, and is not recording the players position.
            //}
        }
    }

    private void RecordData(float deltaTime)
    {
        if (!_recording)
            return;

        // check intervals
        //if (_t > _interval)
        //{
            //_t += deltaTime;
        //    Debug.Log("_t = " + _t);
        //}
        // record this frame
        //else
        //{
            // record target data
            _records[_i] = new TargetRecord(target.position);

            // set next record index
            if (_i < _records.Length - 1)
                _i++;
            else
                _i = 0;

            // set next follow index
            if (_j < _records.Length - 1)
                _j++;
            else
                _j = 0;

            // handle current record
            _record = _records[_j];

            _t = 0f;
        //}
    }

    // used if distance is small
    private void ResetRecordArray()
    {
        _i = 0;
        _j = 1;
        _t = 0f;

        _records = new TargetRecord[_arraySize];

        for (int i = 0; i < _records.Length; i++)
        {
            _records *= new TargetRecord(transform.position);*

}

_record = _records[_j];
}

///


/// Gets the current record.
///

public TargetRecord currentRecord
{
get
{
return _record;
}
}
}

If you just want the camera to follow the player, you can just parent it under the player.
Elsewise you can use a script that sets the cameraposition to the player position with an offset, like I’ve exampled below.

void  Update ()
	{
        newPos = new Vector3 (target.position.x + offsetX, transform.position.y + offsetY, target.position.z + offsetZ);
		transform.position = newPos;
	}