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[i] = new TargetRecord(transform.position);
}
_record = _records[_j];
}
/// <summary>
/// Gets the current record.
/// </summary>
public TargetRecord currentRecord
{
get
{
return _record;
}
}
}
Answer by NFMynster · Feb 20, 2016 at 06:29 AM
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;
}
I need to repeat the player's movement exactly with a small delay. Think of it like a replay system, if Player runs here run here too, if Players jumped here jump here too. This is to create a sidekick that follows the Player and repeats the Player's actions. Think of Donkey $$anonymous$$ong Country, or Sonic 2 with Tails. $$anonymous$$y current code does this but shakes like crazy when repeating the Player's last positions. A camera follow script is different unless it records the Player's last positions and follows that recorded path. Sort of like creating a route and taking it.
You can do this with [Coroutines and yield WaitForSeconds.][1]
Just save the players position and wait, then lerp the camera to the position. [1]: http://docs.unity3d.com/ScriptReference/WaitForSeconds.html
So I am somewhat solving how to make my script smooth. I am Lerping from one recorded point to the next in my array but in Unity's Editor Game Screen the Player jitters but when pushed to mobile is jitters randomly BUT is smooth when it doesn't stutter. It'll take time for me to fix completely. I'll post what code I currently have so far for those who would like it.