I have my camera readjusting on collision, via a linecast, and i’m not sure why but it does kinda a jerky movement… Well, i assume what’s happening is it’s readjusting from a collision, then checking again and readjusting back, but i’m not quite sure how to fix this…
Here’s a video,
I’ve spent hours trying to fix this, watched a million tutorials, even tried Cinemachine(which was subpar from my experience lol).
This is my camera script,
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class CameraMovement : MonoBehaviour
{
Vector3 rotGoal;
[SerializeField] float rotSpeed = 1, rotSens = 2, zoomSpeed = 3, speedZoomMulti = 5, maxSpeedZoom = 15, reAdjustSpeed = 5, defaultXAngle = 10;
[SerializeField] Vector2 maxXRotation;
[SerializeField] Vector3 offset;
Vector2 input;
public Transform target;
Player player;
[SerializeField] float mobileCamAngle = 20;
float currentOffset;
[SerializeField] LayerMask layersToIgnore;
[SerializeField] bool followPlayer = true, lockRotation, lockCamera;
Transform camT;
bool shaking;
float currentSpeedZoom;
[SerializeField] Vector2 speedZoomLevels;
[SerializeField] float shakeDistance = 1, shakeSpeed = 5, distanceToShake = 30, minRange = 0.5f;
[SerializeField] int shakeCount;
Vector3 basePos;
Vector3 previousPos;
float velocity;
public static CameraMovement instance;
private void Awake()
{
transform.parent = null;
instance = this;
camT = Camera.main.transform;
basePos = offset;
player = FindObjectOfType<Player>();
}
void Start()
{
if (!GlobalValues.isMobile)
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
else
{
maxXRotation = Vector2.one * mobileCamAngle;
}
currentOffset = offset.z;
ResetCamera(target.position);
}
public void ToggleCamera(bool lockRotation, bool lockCamera)
{
this.lockRotation = lockRotation;
this.lockCamera = lockCamera;
if (lockRotation)
{
rotGoal = transform.eulerAngles;
}
if (!followPlayer)
{
target = Camera.main.transform;
}
}
public void ResetCamera(Vector3 pos)
{
currentSpeedZoom = 0;
transform.eulerAngles = rotGoal;
transform.position = pos + basePos;
previousPos = pos;
}
private void Update()
{
input = InputManager.input.Player.Look.ReadValue<Vector2>().normalized * rotSens;
}
void FixedUpdate()
{
if (lockCamera) return;
velocity = Mathf.Abs((target.position - previousPos).magnitude);
previousPos = target.position;
currentSpeedZoom = Mathf.Clamp(Mathf.Lerp(currentSpeedZoom, velocity * speedZoomMulti, zoomSpeed * Time.deltaTime), 0, maxSpeedZoom);
if (followPlayer) target = target.transform;
Vector3 newCamPos = target.position - transform.forward * currentOffset + Vector3.up * offset.y;
RaycastHit hit;
if (Physics.Linecast(target.position, newCamPos, out hit, ~layersToIgnore, QueryTriggerInteraction.Ignore))
{
if (currentOffset > 1) currentOffset = hit.distance;
}
else
{
if (currentOffset != offset.z) currentOffset = Mathf.MoveTowards(currentOffset, offset.z + currentSpeedZoom, Time.deltaTime * zoomSpeed);
}
if (!lockRotation)
{
rotGoal += new Vector3(-input.y, input.x);
rotGoal.x = Mathf.Clamp(Mathf.LerpAngle(rotGoal.x, defaultXAngle, reAdjustSpeed * player.animSpeed * Time.deltaTime), maxXRotation.y, maxXRotation.x);
rotGoal.y = Mathf.LerpAngle(rotGoal.y, target.transform.eulerAngles.y, reAdjustSpeed * player.animSpeed * Time.deltaTime);
}
transform.position = newCamPos;
if (GlobalValues.isMobile)
{
rotGoal.y = target.eulerAngles.y;
}
rotGoal.z = 0;
transform.localEulerAngles = new Vector3(transform.eulerAngles.x, transform.eulerAngles.y, 0);
transform.localRotation = Quaternion.Lerp(transform.rotation, Quaternion.Euler(rotGoal), rotSpeed * Time.deltaTime);
}
public void OnDeath()
{
target = GameObject.Find("DeadCameraAnchor").transform;
ToggleCamera(true, true);
transform.parent = target;
transform.localPosition = Vector3.zero;
transform.localEulerAngles = new Vector3(35, 90f, 0);
}
public void ShakeCamera(float distance)
{
if (shaking) return;
shaking = true;
basePos = camT.localPosition;
float distanceMulti = (distanceToShake / distance) / 15;
StopAllCoroutines();
if (distanceMulti < 0.05f) return;
StartCoroutine(ShakeRoutine(distanceMulti));
}
public IEnumerator ShakeRoutine(float distanceMulti)
{
camT.transform.localPosition = basePos;
for (int i = shakeCount; i > -1; i--)
{
Vector3 newPos = basePos + new Vector3(Random.Range(-1f, 1f), Random.Range(-1f, 1f), 0) * shakeDistance * distanceMulti;
while (camT.transform.localPosition != newPos)
{
camT.transform.localPosition = Vector3.MoveTowards(camT.transform.localPosition, newPos, shakeSpeed + distanceMulti * Time.deltaTime);
yield return null;
}
}
while (camT.transform.localPosition != basePos)
{
camT.transform.localPosition = Vector3.MoveTowards(camT.transform.localPosition, basePos, shakeSpeed + distanceMulti * Time.deltaTime);
yield return null;
}
shaking = false;
}
}
(I’ve tried in both fixed and late update, for some reason it’s even more jerky in late update)
Sorry for the lack of detail, not sure what other information i can provide. Does anyone know a good solution for this?
Thanks in advance