Homebound / Scripts / CameraHandler.cs
CameraHandler.cs
Raw
using Cinemachine;
using System.Collections;
using UnityEngine;

/// <summary>
/// Handles the movement and switching of the dolly cameras and the focused camera on the player
/// </summary>
public class CameraHandler : MonoBehaviour
{
    [Header("Camera Components")]
    [SerializeField] float speedOfCameraMovementForDolly = 2f;          // Speed of the camera movement of the dolly camera
    [SerializeField] float taskDelayValue = 2.5f;                       // Delay value for the time the player must remain still before being active when activated
    [SerializeField] CinemachineVirtualCamera dollyVirtualCameraRef;    // Reference for the beginning Dolly Camera
    [SerializeField] CinemachineSmoothPath dollyForVirtualCamera;       // Reference for the dolly track to get path length
    [SerializeField] CinemachineVirtualCamera followVirtualCamera;      // Reference for the Virtual Camera that follows the player for the level
    CinemachineTrackedDolly dollyVirtualCamera;                         // Reference for the beginning Dolly Camera taken from the initial reference field

    bool trigger = false;                   // Trigger for if the camera script is necessary in the beginning 
    Coroutine enablePlayerCoroutine;        // Reference for the player coroutine
    GameOverlay gameOverlayRef;             // Reference for the game overlay component in the current scene

    /// <summary>
    /// Getter for the Follow Camera for the Collision Handler
    /// </summary>
    /// <returns>Player Follow Camera</returns>
    public CinemachineVirtualCamera GetFollowCamera()
    {
        if (followVirtualCamera == null)
            return null;
        else
            return followVirtualCamera;
    }

    void Awake()
    {
        if (dollyVirtualCameraRef != null)
        {
            dollyVirtualCamera = dollyVirtualCameraRef.GetCinemachineComponent<CinemachineTrackedDolly>();
            dollyVirtualCamera.m_PathPosition = 0f;
            trigger = true;
        }
        else 
            return;
    }

    void Start()
    {
        if (trigger)
            GetComponent<Movement>().enabled = false;

        if (GameOverlay.Instance != null) 
            gameOverlayRef = GameOverlay.Instance;
    }

    void Update()
    {
        if (!MainMenu.IsPaused)
        {
            if (trigger)
            {
                if (Input.GetKey(KeyCode.Space))
                    EnablePlayerStart(true);        // When the player presses Space the beginning cutscene will be skipped and the 
                
                // Moves the dolly camera along the path
                dollyVirtualCamera.m_PathPosition += (Time.deltaTime * speedOfCameraMovementForDolly);

                if (dollyVirtualCamera.m_PathPosition >= dollyForVirtualCamera.PathLength)
                    EnablePlayerStart(false);       // Indicator if the player has not pressed while the dolly camera has reached the end of the level showing
            }
        }
    }

    /// <summary>
    /// Skips the starting scene of the dolly camera moving through the level to give the player a glimpse
    /// </summary>
    /// <param name="skipTrigger">If the starting sequence should be skipped and the player can begin moving</param>
    void EnablePlayerStart(bool skipTrigger) => enablePlayerCoroutine ??= StartCoroutine(EnablePlayerCoroutine(skipTrigger));

    /// <summary>
    /// Coroutine that enables and disables the necessary cameras for the player to begin playing the level while the virtual camera maintains focus on them
    /// </summary>
    /// <param name="skipTrigger">Determinant if the dolly camera should jump towards the player virtual camera that follows them</param>
    /// <returns></returns>
    IEnumerator EnablePlayerCoroutine(bool skipTrigger)
    {
        if (skipTrigger)
            dollyVirtualCamera.m_PathPosition = dollyForVirtualCamera.PathLength;
         
        // Switch main camera
        dollyVirtualCameraRef.enabled = false;
        followVirtualCamera.enabled = true;

        yield return new WaitForSeconds(taskDelayValue);

        // Allows player movement and starts the timer
        GetComponent<Movement>().enabled = true;
        if (gameOverlayRef != null) 
            gameOverlayRef.StartTimer();

        trigger = false;
    }

    /// <summary>
    /// Prevents the virtual camera from following the player further by detatching the player from the follow field
    /// </summary>
    public void DisableFollowCamera() => followVirtualCamera.Follow = null;
}