I have a problem with my ViewBobScript, it snaps back to the lerps start position for 1 frame.
Here is a Recreation/Video of my problem: (Due to the framerate of the video not matching up to the game it might look as if the lerp is not smooth, while it is. the problem is the snap at the beginning and end of the video and seems to occur at irregular intervals)
And here is my code:
private float aTimer;
private int viewBobPath = 1;
private float startViewBob;
private float viewBobPathTimer;
private void ViewBob()
{
startViewBob = viewBobSpeed / 2;
aTimer += Time.deltaTime;
viewBobPathTimer += Time.deltaTime;
if (aTimer > startViewBob * viewBobPath) { viewBobPath++; }
if (viewBobPathTimer > startViewBob) { viewBobPathTimer = 0; }
if (aTimer < (viewBobSpeed * 2))
{
switch (viewBobPath)
{
case 1:
playerCam.transform.localPosition = Vector3.Lerp(new Vector3(-viewBobHorizontal / 2, 0, 0), new Vector3(0, -viewBobVertical, 0), viewBobPathTimer);
break;
case 2:
playerCam.transform.localPosition = Vector3.Lerp(new Vector3(0, -viewBobVertical, 0), new Vector3(viewBobHorizontal / 2, 0, 0), viewBobPathTimer);
break;
case 3:
playerCam.transform.localPosition = Vector3.Lerp(new Vector3(viewBobHorizontal / 2, 0, 0), new Vector3(0, -viewBobVertical, 0), viewBobPathTimer);
break;
case 4:
playerCam.transform.localPosition = Vector3.Lerp(new Vector3(0, -viewBobVertical, 0), new Vector3(-viewBobHorizontal / 2, 0, 0), viewBobPathTimer);
break;
}
}
else { aTimer = 0; viewBobPathTimer = 0; viewBobPath = 1; }
}
Also, I know the unity character controller has ViewBobbing. but this is not an option for my application.
Thank you so so much for helping!
Edit: This is called from the update function, although I have tried Fixed and late update both don't change, solve or reduce the problem.
Although my script works and I'm continuing with my project, if you know why my code above didn't work/did the Snap I would appreciate knowing so I learn from it!
I would take a different approach, adding Time.deltaTime
to one field, then calculating which path and what t
param that field corresponds to. Mathf.Repeat is useful for this.
[SerializeField] int pathIndex;
[SerializeField] float pathT;
[SerializeField] float aTimer;
[SerializeField] float pathDuration = 1f; // how long each path takes in seconds
private void ViewBob()
{
// update aTimer but wrap around at pathDuration x 4 ( [0, 4pD) )
aTimer = Mathf.Repeat(aTimer + Time.deltaTime, pathDuration * 4f);
// How many path durations is aTimer along? ( {0, 1, 2, 3} )
pathIndex = Mathf.FloorToInt(aTimer/pathDuration);
// How far into the current path duration is aTimer? ( [0,1) )
pathT = Mathf.Repeat(aTimer, pathDuration) / pathDuration;
Vector3 fromVector;
Vector3 toVector;
// assign to/from vectors based on pathIndex
switch (pathIndex)
{
default:
case 0:
fromVector = new Vector3(-viewBobHorizontal / 2, 0, 0);
toVector = new Vector3(0, -viewBobVertical, 0);
break;
case 1:
fromVector = new Vector3(0, -viewBobVertical, 0);
toVector = new Vector3(viewBobHorizontal / 2, 0, 0);
break;
case 2:
fromVector = new Vector3(viewBobHorizontal / 2, 0, 0);
toVector = new Vector3(0, -viewBobVertical, 0);
break;
case 3:
fromVector = new Vector3(0, -viewBobVertical, 0);
toVector = new Vector3(-viewBobHorizontal / 2, 0, 0);
break;
}
// lerp position based on pathT and the to/from vectors
playerCam.transform.localPosition = Vector3.Lerp(fromVector, toVector, pathT);
}