204 lines
6.2 KiB
C#
204 lines
6.2 KiB
C#
|
using System;
|
||
|
using System.Collections;
|
||
|
using Cinemachine;
|
||
|
using UnityEngine;
|
||
|
|
||
|
namespace RND
|
||
|
{
|
||
|
|
||
|
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, NullableVector3 overwrites)
|
||
|
{
|
||
|
TargetFollower.SetTarget(target, instant, overwrites);
|
||
|
}
|
||
|
|
||
|
public void SetTarget(Transform[] targetsTransforms, CameraGroupTargetParameters[] parameters, bool instant, NullableVector3 overwrites)
|
||
|
{
|
||
|
_targetGroup = GetTargetGroup(targetsTransforms, parameters);
|
||
|
|
||
|
TargetFollower.SetTarget(_targetGroup.transform, instant, overwrites);
|
||
|
}
|
||
|
|
||
|
|
||
|
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);
|
||
|
}
|
||
|
}
|
||
|
}
|