Files
ScienceLab.FrictionForce/Assets/Scripts/Rocket/RocketCameraController.cs
2026-05-29 18:30:19 +03:00

185 lines
5.4 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine;
public class RocketCameraController : MonoBehaviour
{
[Header("Êàìåðà")]
[SerializeField] private Camera mainCamera;
[SerializeField] private Transform rocketRoot;
[SerializeField] private float baseFOV = 60f;
private Vector3 _cameraStartPos;
private Quaternion _cameraStartRot;
private Vector3 _rocketStartPos;
private Vector3 _camVelocity = Vector3.zero;
private bool _isActive;
private RocketFlightCore _core;
private float _flightTimer;
private float _swayTime;
private float _currentShake;
private float _targetFOV;
public void Initialize(RocketFlightCore core)
{
_core = core;
_cameraStartPos = mainCamera.transform.position;
_cameraStartRot = mainCamera.transform.rotation;
_rocketStartPos = rocketRoot != null ? rocketRoot.position : Vector3.zero;
baseFOV = mainCamera.fieldOfView;
_targetFOV = baseFOV;
}
public void StartFlight()
{
_isActive = true;
_flightTimer = 0f;
_swayTime = 0f;
_camVelocity = Vector3.zero;
_currentShake = 0f;
}
public void StopFlight()
{
_isActive = false;
}
public void ResetCamera()
{
_isActive = false;
_flightTimer = 0f;
_camVelocity = Vector3.zero;
_currentShake = 0f;
mainCamera.transform.position = _cameraStartPos;
mainCamera.transform.rotation = _cameraStartRot;
mainCamera.fieldOfView = baseFOV;
}
public void TriggerSonicBoom()
{
StartCoroutine(SonicBoomShake());
}
public void SwitchToSpaceDrift() { }
public void StartIgnitionShake(float shakeMultiplier)
{
StartCoroutine(IgnitionShake(shakeMultiplier));
}
private void Update()
{
if (!_isActive || _core == null || mainCamera == null) return;
_flightTimer += Time.deltaTime;
_swayTime += Time.deltaTime;
UpdateCameraFollow();
UpdateFOV();
UpdateCameraRotation();
}
private void UpdateCameraFollow()
{
float rocketVisualY = rocketRoot.position.y - _rocketStartPos.y;
float speedNorm = _core.GetSpeedNormalized();
float spaceProgress = _core.GetSpaceProgress();
float swayX = Mathf.Sin(_swayTime * 13.7f) * speedNorm * 0.06f;
float swayY = Mathf.Sin(_swayTime * 9.3f) * speedNorm * 0.03f;
float smoothTime = _core.FuelCutoff
? 0.4f
: Mathf.Lerp(0.04f, 0.12f, spaceProgress);
Vector3 target = _cameraStartPos
+ Vector3.up * rocketVisualY
+ new Vector3(swayX, swayY, 0f);
mainCamera.transform.position = Vector3.SmoothDamp(
mainCamera.transform.position,
target,
ref _camVelocity,
smoothTime);
if (_currentShake > 0f)
{
_currentShake = Mathf.Lerp(_currentShake, 0f, Time.deltaTime * 3f);
mainCamera.transform.position += new Vector3(
Random.Range(-_currentShake, _currentShake),
Random.Range(-_currentShake * 0.5f, _currentShake * 0.5f),
0f);
}
}
private void UpdateFOV()
{
float speedNorm = _core.GetSpeedNormalized();
float spaceProgress = _core.GetSpaceProgress();
if (_core.FuelCutoff)
{
_targetFOV = Mathf.Lerp(_targetFOV, baseFOV, Time.deltaTime * 1.5f);
}
else if (spaceProgress > 0.1f)
{
_targetFOV = Mathf.Lerp(baseFOV + speedNorm * 15f, baseFOV + 22f, Mathf.Clamp01(spaceProgress * 2f));
}
else
{
_targetFOV = baseFOV + speedNorm * 20f;
}
mainCamera.fieldOfView = Mathf.Lerp(mainCamera.fieldOfView, _targetFOV, Time.deltaTime * 5f);
}
private void UpdateCameraRotation()
{
float speedNorm = _core.GetSpeedNormalized();
float spaceProgress = _core.GetSpaceProgress();
float roll = Mathf.Sin(_swayTime * 5f) * speedNorm * 0.6f;
float tiltForward = spaceProgress > 0.3f
? Mathf.Lerp(0f, 4f, (spaceProgress - 0.3f) / 0.7f)
: 0f;
mainCamera.transform.rotation = Quaternion.Slerp(
mainCamera.transform.rotation,
_cameraStartRot * Quaternion.Euler(tiltForward, 0f, roll),
Time.deltaTime * 2f);
}
private IEnumerator IgnitionShake(float shakeMultiplier)
{
float elapsed = 0f;
float duration = 2.0f;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
float progress = elapsed / duration;
float power = progress < 0.15f
? Mathf.Lerp(0f, 0.5f * shakeMultiplier, progress / 0.15f)
: Mathf.Lerp(0.5f * shakeMultiplier, 0.02f * shakeMultiplier, (progress - 0.15f) / 0.85f);
_currentShake = power;
yield return null;
}
_currentShake = 0f;
}
private IEnumerator SonicBoomShake()
{
float elapsed = 0f;
float duration = 0.6f;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
_currentShake = Mathf.Lerp(0.4f, 0f, elapsed / duration);
yield return null;
}
_currentShake = 0f;
}
}