metahunt/Assets/Scripts/Utils/CameraFollow.cs
2024-02-11 13:53:18 +05:30

201 lines
6.1 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using Random = UnityEngine.Random;
public class CameraFollow : MonoBehaviour
{
public UpdateFrameType UpdateType;
public Transform target;
public Vector2 offset;
public float yMinLimit, yMaxLimit;
public float xSpeed, ySpeed;
public float lookSensitivity;
public float distance = 3;
public float x, y;
public bool isAiming= false;
public float aimingFovIncrease = -20;
[Header("Moving effects")]
public float movingShakeIntensity;
float defaultFov;
public float movingFovIncrease = 10;
public float movingZoomDist=1;
public float movingEffectsSpeed = 0.4f;
public float movingEffectsThershold;
public float currentTargetSpeed;
public static CameraFollow instance;
public bool isViewObstructed;
public float obstacleAvoidanceDistMult = 2f;
public float pitchZoomThreshold = -25;
public float pitchZoomDist = 1.5f;
private void Awake()
{
instance = this;
isPaused = false;
defaultFov = Camera.main.fieldOfView;
}
void Start(){
SettingsManager.instance.OnSettingsChanged.AddListener(OnSettingsChanged);
OnSettingsChanged();
}
void OnSettingsChanged(){
lookSensitivity = PlayerPrefs.GetFloat(SettingsManager.LOOKSENS_PREF_KEY);
movingFovIncrease = SettingsManager.instance.cameraFovSlider.value;
movingZoomDist = SettingsManager.instance.cameraZoomSlider.value;
}
// Update is called once per frame
void Update()
{
if(UpdateType == UpdateFrameType.Normal) { UpdateFrame(); }
}
private void LateUpdate()
{
x += Input.GetAxis("Mouse X") * xSpeed * 0.02f * lookSensitivity;
y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f * lookSensitivity;
if(UpdateType == UpdateFrameType.Late) { UpdateFrame(); }
}
private void FixedUpdate()
{
if(UpdateType == UpdateFrameType.Fixed) { UpdateFrame(); }
}
private bool isPaused = false;
public static void Pause(){
instance.isPaused = true;
}
public static void Resume(){
instance.isPaused = false;
}
Vector3 targetLastPos;
float movingEffectOffsetY = 0;
float obstacleOffsetY=0;
float pitchZoom=0;
void UpdateFrame()
{
if(isPaused){return;}
if(target == null) { return; }
// currentTargetSpeed = (target.position - targetLastPos).sqrMagnitude;
// targetLastPos = target.position;
if (distance < 2) distance = 2;
// distance -= Input.GetAxis("Mouse ScrollWheel") * 2;
var pos = Input.mousePosition;
var dpiScale = 1f;
if (Screen.dpi < 1) dpiScale = 1;
if (Screen.dpi < 200) dpiScale = 1;
else dpiScale = Screen.dpi / 200f;
if (pos.x < 380 * dpiScale && Screen.height - pos.y < 250 * dpiScale) return;
// comment out these two lines if you don't want to hide mouse curser or you have a UI button
Cursor.visible = UIManager.isPaused;
Cursor.lockState = UIManager.isPaused ? CursorLockMode.None:CursorLockMode.Locked;
float fovDelta = 0;
if(currentTargetSpeed > movingEffectsThershold){
fovDelta = movingFovIncrease;
movingEffectOffsetY = Mathf.Lerp(movingEffectOffsetY, movingZoomDist, movingEffectsSpeed);
}else{
fovDelta =0;
movingEffectOffsetY = Mathf.Lerp(movingEffectOffsetY, 0, movingEffectsSpeed);
}
float m_obstacleZoomDist =0;
isViewObstructed=false;
RaycastHit hit = new RaycastHit();
if(Physics.Linecast(target.position + (transform.forward * -obstacleAvoidanceDistMult * 2), target.position,out hit)){
if(hit.collider.tag == "Player"){}else{
// m_obstacleZoomDist = Vector3.Distance(transform.position, hit.point) * obstacleAvoidanceDistMult;
m_obstacleZoomDist=obstacleAvoidanceDistMult;
isViewObstructed=true;
}
}
obstacleOffsetY = Mathf.Lerp(obstacleOffsetY, m_obstacleZoomDist, movingEffectsSpeed*5f);
if(isAiming){
fovDelta = aimingFovIncrease;
}
Camera.main.fieldOfView = Mathf.Lerp(Camera.main.fieldOfView, defaultFov + fovDelta, movingEffectsSpeed *(isAiming ? 10f:1));
y = ClampAngle(y, yMinLimit, yMaxLimit);
var rotation = Quaternion.Euler(y, x, 0);
var position = rotation * new Vector3(0.0f, 0.0f, -distance) + target.transform.position;
pitchZoom = Mathf.Lerp(pitchZoom,y < pitchZoomThreshold ? pitchZoomDist : 0, movingEffectsSpeed);
position += transform.right * offset.x;
position += transform.forward *( offset.y + movingEffectOffsetY + obstacleOffsetY + pitchZoom);
transform.rotation = rotation;
transform.position = position;
if (Mathf.Abs(prevDistance - distance) > 0.001f)
{
prevDistance = distance;
var rot = Quaternion.Euler(y, x, 0);
var po = rot * new Vector3(0.0f, 0.0f, -distance) + target.transform.position;
transform.rotation = rot;
transform.position = po;
}
if(shakeIndex>0){
shakeIndex--;
float progression = (float)shakeIndex / (float)SHAKE_FRAMES;
transform.position += new Vector3(Random.Range(-1f,1f),Random.Range(-1f,1f),Random.Range(-1f,1f)) * shakeIntensity * progression;
}
}
public int shakeIndex =0;
private float shakeIntensity;
const int SHAKE_FRAMES = 25;
public static void Shake(float intensity){
instance.shakeIndex = SHAKE_FRAMES;
instance.shakeIntensity = Mathf.Clamp(intensity,0,0.5f);
}
float prevDistance;
static float ClampAngle(float angle, float min, float max)
{
if (angle < -360)
angle += 360;
if (angle > 360)
angle -= 360;
return Mathf.Clamp(angle, min, max);
}
}
public enum UpdateFrameType
{
Normal,
Fixed,
Late
}