Files
BABA_YAGA/Assets/Scripts/Camera Controller/CameraController.cs

215 lines
9.6 KiB
C#
Raw Normal View History

2026-03-27 12:27:50 +07:00
using System; // For Action event
2026-03-26 20:27:19 +07:00
using UnityEngine;
namespace OnlyScove.Scripts
{
public class CameraController : MonoBehaviour
{
2026-03-27 12:27:50 +07:00
public enum CameraViewMode { ThirdPerson, FirstPerson }
2026-03-27 12:08:16 +07:00
[SerializeField] InputReader inputReader;
2026-03-27 12:27:50 +07:00
[SerializeField] Transform followTarget; // Player's root for TPV
2026-03-27 12:08:16 +07:00
[SerializeField] float positionSmoothTime = 0.12f;
[SerializeField] float rotationSmoothTime = 5f;
2026-03-26 20:27:19 +07:00
[SerializeField] Vector2 framingOffset;
2026-03-27 12:08:16 +07:00
[Header("Components")]
[SerializeField] private CameraRotationHandler rotationHandler = new CameraRotationHandler();
[SerializeField] private CameraZoomHandler zoomHandler = new CameraZoomHandler();
[SerializeField] private CameraCollisionHandler collisionHandler = new CameraCollisionHandler();
[SerializeField] private CameraOcclusionTransparency occlusionTransparency = new CameraOcclusionTransparency();
[SerializeField] private CameraDynamicFOV dynamicFOV = new CameraDynamicFOV();
[SerializeField] private CameraCharacterFading characterFading = new CameraCharacterFading();
[SerializeField] private CameraSideBias sideBias = new CameraSideBias();
[SerializeField] private CameraShakeManager shakeManager = new CameraShakeManager();
2026-03-27 12:27:50 +07:00
[Header("First Person View Settings")]
[SerializeField] Transform fpvTarget; // Specific transform on the player (e.g., eye level)
[SerializeField] float fpvPositionSmoothTime = 0.05f;
2026-03-27 20:20:06 +07:00
[SerializeField] float fpvRotationSmoothTime = 20f;
2026-03-27 12:27:50 +07:00
[SerializeField] float fpvFOV = 80f;
[SerializeField] float transitionDuration = 0.3f;
[SerializeField] float tpvBaseFOV = 60f; // Existing base FOV for TPV
2026-03-27 12:08:16 +07:00
private Vector3 _currentVelocity;
private Camera _cam;
2026-03-27 12:27:50 +07:00
private CameraViewMode _currentViewMode = CameraViewMode.ThirdPerson;
private CameraViewMode _targetViewMode = CameraViewMode.ThirdPerson;
private float _transitionTimer = 0f;
private bool _inTransition = false;
2026-03-27 20:20:06 +07:00
public CameraViewMode CurrentViewMode => _currentViewMode;
2026-03-27 12:27:50 +07:00
// Properties to get current smoothing values based on view mode
private float CurrentPositionSmoothTime => _currentViewMode == CameraViewMode.FirstPerson ? fpvPositionSmoothTime : positionSmoothTime;
private float CurrentRotationSmoothTime => _currentViewMode == CameraViewMode.FirstPerson ? fpvRotationSmoothTime : rotationSmoothTime;
private void OnEnable()
{
if (inputReader != null)
{
inputReader.OnToggleViewEvent += ToggleCameraView;
}
}
private void OnDisable()
{
if (inputReader != null)
{
inputReader.OnToggleViewEvent -= ToggleCameraView;
}
}
2026-03-26 20:27:19 +07:00
private void Start()
{
2026-03-27 12:08:16 +07:00
_cam = GetComponent<Camera>();
2026-03-26 20:27:19 +07:00
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
2026-03-27 12:27:50 +07:00
2026-03-27 12:08:16 +07:00
rotationHandler.Initialize(transform);
2026-03-27 12:27:50 +07:00
dynamicFOV.Initialize(tpvBaseFOV: tpvBaseFOV, fpvFOV: fpvFOV); // Pass TPV and FPV base FOVs
2026-03-26 20:27:19 +07:00
}
private void Update()
{
2026-03-27 12:27:50 +07:00
HandleViewTransition();
2026-03-26 20:27:19 +07:00
if (inputReader != null)
{
2026-03-27 12:27:50 +07:00
// Input-related updates are handled differently based on view mode
rotationHandler.HandleRotation(inputReader, followTarget, CurrentRotationSmoothTime, _currentViewMode);
if (_currentViewMode == CameraViewMode.ThirdPerson)
{
zoomHandler.HandleZoom(inputReader);
sideBias.HandleSideBias(inputReader);
}
else
{
// Disable side bias and zoom in FPV
sideBias.HandleSideBias(null); // Pass null to effectively disable
zoomHandler.HandleZoom(null); // Pass null to effectively disable
}
dynamicFOV.HandleDynamicFOV(_cam, inputReader, _currentViewMode);
2026-03-26 20:27:19 +07:00
}
2026-03-27 12:27:50 +07:00
Vector3 focusPosition;
float targetDistance;
2026-03-26 20:27:19 +07:00
2026-03-27 12:27:50 +07:00
if (_currentViewMode == CameraViewMode.ThirdPerson)
{
// TPV specific calculations
2026-03-27 20:20:06 +07:00
transform.rotation = rotationHandler.CurrentRotation; // Set camera rotation from handler
2026-03-27 12:27:50 +07:00
focusPosition = followTarget.position + rotationHandler.CurrentRotation * new Vector3(framingOffset.x + sideBias.CurrentSideBias, framingOffset.y, 0);
targetDistance = collisionHandler.CheckCollision(focusPosition, rotationHandler.CurrentRotation, zoomHandler.CurrentDistance, zoomHandler.MinDistance);
characterFading.HandleCharacterFading(targetDistance);
occlusionTransparency.HandleTransparency(transform, focusPosition);
}
else // FirstPerson
{
// FPV specific calculations
2026-03-27 20:20:06 +07:00
// Player's horizontal rotation (body) follows mouse YAW
if (followTarget != null)
{
followTarget.rotation = rotationHandler.PlanarRotation; // Sync body to camera yaw
}
if (fpvTarget != null)
{
fpvTarget.rotation = rotationHandler.CurrentRotation; // Sync head/eyes to full camera rotation
}
transform.rotation = rotationHandler.CurrentRotation; // Set camera rotation from handler (which includes vertical)
2026-03-27 12:27:50 +07:00
focusPosition = fpvTarget.position;
targetDistance = 0; // FPV has no distance to player
2026-03-26 20:27:19 +07:00
2026-03-27 12:27:50 +07:00
// Disable TPV-specific effects
characterFading.HandleCharacterFading(0); // Fully opaque character in FPV
occlusionTransparency.HandleTransparency(transform, fpvTarget.position); // Can still have occlusion transparency for environment in FPV
}
// Calculate target position using the currently set transform.rotation
2026-03-27 20:20:06 +07:00
Vector3 targetPosition = focusPosition - transform.rotation * new Vector3(0, 0, targetDistance);
2026-03-27 12:08:16 +07:00
// Handle camera shake
shakeManager.HandleShake();
2026-03-27 12:27:50 +07:00
2026-03-27 12:08:16 +07:00
// Apply final position and rotation
2026-03-27 12:27:50 +07:00
transform.position = Vector3.SmoothDamp(transform.position, targetPosition, ref _currentVelocity, CurrentPositionSmoothTime) + shakeManager.ShakeOffset;
}
private void ToggleCameraView()
{
if (_inTransition) return; // Prevent multiple toggles during transition
_targetViewMode = (_currentViewMode == CameraViewMode.ThirdPerson) ? CameraViewMode.FirstPerson : CameraViewMode.ThirdPerson;
2026-03-27 20:20:06 +07:00
Debug.Log($"[CameraController] Toggling view from {_currentViewMode} to {_targetViewMode}");
2026-03-27 12:27:50 +07:00
_inTransition = true;
_transitionTimer = 0f;
}
private void HandleViewTransition()
{
if (!_inTransition) return;
_transitionTimer += Time.deltaTime;
float t = _transitionTimer / transitionDuration;
t = Mathf.Clamp01(t); // Clamp t between 0 and 1
// Smoothly interpolate parameters during transition
if (_currentViewMode == CameraViewMode.ThirdPerson && _targetViewMode == CameraViewMode.FirstPerson)
{
// TPV -> FPV transition
// Interpolate FOV
_cam.fieldOfView = Mathf.Lerp(dynamicFOV.CurrentTpvBaseFOV, fpvFOV, t);
2026-03-27 20:20:06 +07:00
// Rotate player body to match camera's intended horizontal look direction
if (followTarget != null)
{
followTarget.rotation = Quaternion.Slerp(followTarget.rotation, rotationHandler.PlanarRotation, t);
}
2026-03-27 12:27:50 +07:00
// Interpolate position and rotation
transform.position = Vector3.Lerp(transform.position, fpvTarget.position, t);
transform.rotation = Quaternion.Slerp(transform.rotation, fpvTarget.rotation, t);
}
else if (_currentViewMode == CameraViewMode.FirstPerson && _targetViewMode == CameraViewMode.ThirdPerson)
{
// FPV -> TPV transition
// Interpolate FOV
_cam.fieldOfView = Mathf.Lerp(fpvFOV, dynamicFOV.CurrentTpvBaseFOV, t);
}
if (t >= 1f)
{
_currentViewMode = _targetViewMode;
2026-03-27 20:20:06 +07:00
Debug.Log($"[CameraController] View transition complete. Current mode: {_currentViewMode}");
2026-03-27 12:27:50 +07:00
_inTransition = false;
2026-03-27 20:20:06 +07:00
// Initialize rotation handler based on new view mode
if (_currentViewMode == CameraViewMode.FirstPerson && fpvTarget != null)
{
rotationHandler.InitializeFPV(fpvTarget); // Initialize FPV rotation handler
}
else
{
rotationHandler.Initialize(transform); // Initialize TPV rotation handler
}
2026-03-27 12:27:50 +07:00
// Ensure FOV is set correctly at the end of transition
_cam.fieldOfView = (_currentViewMode == CameraViewMode.FirstPerson) ? fpvFOV : dynamicFOV.CurrentTpvBaseFOV;
}
2026-03-26 20:27:19 +07:00
}
public void Shake(float intensity, float duration)
{
2026-03-27 12:08:16 +07:00
shakeManager.Shake(intensity, duration);
2026-03-26 20:27:19 +07:00
}
2026-03-27 12:08:16 +07:00
public void TriggerFallImpactShake(float fallHeight)
2026-03-26 20:27:19 +07:00
{
2026-03-27 12:08:16 +07:00
shakeManager.TriggerFallImpactShake(fallHeight);
2026-03-26 20:27:19 +07:00
}
2026-03-27 12:08:16 +07:00
public Quaternion PlanarRotation => rotationHandler.PlanarRotation;
2026-03-26 20:27:19 +07:00
}
}