199 lines
5.6 KiB
C#
199 lines
5.6 KiB
C#
using System;
|
|
using System.Collections;
|
|
using Cinemachine;
|
|
using UnityEngine;
|
|
|
|
public partial class CameraController : MonoBehaviour
|
|
{
|
|
public event Action OnCameraChanged;
|
|
public event Action OnCameraBlendEnded;
|
|
public Camera Main { get; private set; }
|
|
public CameraItem ActiveCamera { get; private set; }
|
|
|
|
[SerializeField] private CameraItem[] _cameras;
|
|
[SerializeField] private Camera _uiCamera;
|
|
|
|
private CinemachineBrain _brain;
|
|
private Camera[] _mainChildCameras;
|
|
private CinemachineTargetGroup _targetGroup;
|
|
public CameraTargetFollower TargetFollower { get; private set; }
|
|
|
|
private void Start()
|
|
{
|
|
CheckCameras();
|
|
|
|
Main = Camera.main;
|
|
|
|
if (Main != null)
|
|
{
|
|
_mainChildCameras = Main.gameObject.GetComponentsInChildren<Camera>();
|
|
_brain = Main.GetComponent<CinemachineBrain>();
|
|
}
|
|
else
|
|
throw new NullReferenceException("MainCamera is null");
|
|
|
|
InitSwitchCameras();
|
|
|
|
UI.Canvas.worldCamera = _uiCamera;
|
|
|
|
|
|
_brain.m_CameraActivatedEvent.AddListener(
|
|
(cam1, cam2) =>
|
|
{
|
|
OnCameraChanged?.Invoke();
|
|
StartCoroutine(InvokeCameraBlendEnded(_brain.ActiveBlend?.Duration ?? 0f));
|
|
});
|
|
|
|
TargetFollower = CameraTargetFollower.CreateTarget();
|
|
StartCoroutine(SetFollowTargetCycle(TargetFollower.transform));
|
|
StartCoroutine(SetLookAtTargetCycle(TargetFollower.transform));
|
|
|
|
if(_cameras.Length > 0)
|
|
SetActive(_cameras[0]);
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if(_mainChildCameras.Length > 0)
|
|
foreach (Camera addCamera in _mainChildCameras)
|
|
{
|
|
addCamera.orthographic = Main.orthographic;
|
|
addCamera.orthographicSize = Main.orthographicSize;
|
|
addCamera.fieldOfView = Main.fieldOfView;
|
|
}
|
|
|
|
SwitchCamerasTick();
|
|
}
|
|
|
|
private IEnumerator InvokeCameraBlendEnded(float delay)
|
|
{
|
|
yield return new WaitForSecondsRealtime(delay);
|
|
OnCameraBlendEnded?.Invoke();
|
|
}
|
|
|
|
private void CheckCameras()
|
|
{
|
|
foreach (CameraItem cameraItem in _cameras)
|
|
{
|
|
if (cameraItem.camera == null)
|
|
throw new NullReferenceException();
|
|
}
|
|
}
|
|
|
|
private void DisableAllCameras()
|
|
{
|
|
foreach (CameraItem item in _cameras)
|
|
item.camera.gameObject.SetActive(false);
|
|
}
|
|
|
|
public void SetActive(CameraTypeEnum type)
|
|
{
|
|
DisableAllCameras();
|
|
|
|
CameraItem cameraItem = Array.Find(_cameras, item => item.type == type);
|
|
|
|
if (cameraItem == null)
|
|
throw new Exception($"Cant find camera with type {type}");
|
|
|
|
cameraItem.camera.gameObject.SetActive(true);
|
|
ActiveCamera = cameraItem;
|
|
}
|
|
|
|
public void SetActive(CameraItem cameraItem)
|
|
{
|
|
DisableAllCameras();
|
|
|
|
if (cameraItem == null)
|
|
throw new NullReferenceException();
|
|
|
|
cameraItem.camera.gameObject.SetActive(true);
|
|
ActiveCamera = cameraItem;
|
|
}
|
|
|
|
public void SetTarget(Transform target, bool instant = true)
|
|
{
|
|
TargetFollower.SetTarget(target, instant);
|
|
}
|
|
|
|
public void SetTarget(Transform[] targetsTransforms, CameraGroupTargetParameters[] parameters = null, bool instant = true)
|
|
{
|
|
_targetGroup = GetTargetGroup(targetsTransforms, parameters);
|
|
|
|
TargetFollower.SetTarget(_targetGroup.transform, instant);
|
|
}
|
|
|
|
|
|
private CinemachineTargetGroup GetTargetGroup(Transform[] targetsTransforms, CameraGroupTargetParameters[] parameters = null)
|
|
{
|
|
if (_targetGroup == null)
|
|
{
|
|
var go = new GameObject("TargetGroup");
|
|
_targetGroup = go.AddComponent<CinemachineTargetGroup>();
|
|
go.transform.SetParent(transform);
|
|
}
|
|
|
|
_targetGroup.m_Targets = new CinemachineTargetGroup.Target[targetsTransforms.Length];
|
|
|
|
if (parameters == null)
|
|
{
|
|
parameters = new CameraGroupTargetParameters[targetsTransforms.Length];
|
|
parameters.ForEach(() => new CameraGroupTargetParameters());
|
|
}
|
|
else if (parameters.Length < targetsTransforms.Length)
|
|
throw new Exception("Parameters array length less then elements count");
|
|
|
|
for (var i = 0; i < _targetGroup.m_Targets.Length; i++)
|
|
{
|
|
_targetGroup.m_Targets[i].target = targetsTransforms[i];
|
|
_targetGroup.m_Targets[i].weight = parameters[i].Weight;
|
|
_targetGroup.m_Targets[i].radius = parameters[i].Radius;
|
|
}
|
|
|
|
return _targetGroup;
|
|
}
|
|
|
|
private IEnumerator SetFollowTargetCycle(Transform target, bool reenable = true)
|
|
{
|
|
void SetFollow(CinemachineVirtualCamera cam)
|
|
{
|
|
cam.m_Follow = target;
|
|
|
|
if(reenable)
|
|
cam.enabled = true;
|
|
}
|
|
|
|
if(reenable)
|
|
{
|
|
foreach (CameraItem cam in _cameras)
|
|
cam.camera.enabled = false;
|
|
}
|
|
|
|
yield return null;
|
|
|
|
foreach (CameraItem cam in _cameras)
|
|
SetFollow(cam.camera);
|
|
}
|
|
|
|
private IEnumerator SetLookAtTargetCycle(Transform target, bool reenable = true)
|
|
{
|
|
void SetLookAt(CinemachineVirtualCamera cam)
|
|
{
|
|
cam.m_LookAt = target;
|
|
|
|
if(reenable)
|
|
cam.enabled = true;
|
|
}
|
|
|
|
if(reenable)
|
|
{
|
|
foreach (CameraItem cam in _cameras)
|
|
cam.camera.enabled = false;
|
|
}
|
|
|
|
yield return null;
|
|
|
|
foreach (CameraItem cam in _cameras)
|
|
SetLookAt(cam.camera);
|
|
}
|
|
}
|