201 lines
6.1 KiB
C#
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
|
|
} |