Greetings, I’m currently working on my CameraManager to listen for CinemachineBrain’s CameraActivatedEvent, and I want it to enable/disable all my MonoBehaviour scripts attached to the camera for both camera before and after transmitting.
Everything works great, but something confuses me, my SetCameraScriptsActive method appears to be functioning correctly except that it doesn’t actually set enabled to the expected value. The log also shows "MainCameraScript is False", so it does set them but not ACTUALLY set correctly.
So why aren’t the scripts being disabled/enabled as expected, even though everything seems fine?
Here’s my code:
using UnityEngine;
using Cinemachine;
[DefaultExecutionOrder(100)]
public class CameraManager : MonoBehaviour
{
private static CameraManager _instance;
public static CameraManager Instance
{
get => _instance;
private set => _instance = value;
}
private void Awake()
{
SingletonManager.Instance.InitializeSingleton(ref _instance, this);
}
private Camera mainCamera;
private CinemachineBrain cinemachineBrain;
private ICinemachineCamera liveVirtualCamera;
private bool isTransitioning = false;
public void SetCameraScriptsActive(
ICinemachineCamera vCam,
bool active
)
{
if (vCam == null)
{
Debug.LogWarning("VirtualCamera is null!");
return;
}
MonoBehaviour vCamMono = vCam as MonoBehaviour;
MonoBehaviour[] scripts = vCamMono.gameObject.GetComponents<MonoBehaviour>();
foreach (MonoBehaviour script in scripts)
{
switch (script)
{
case MainCameraScript _:
script.enabled = active;
Debug.Log($"{script.GetType().Name} is {script.enabled}");
break;
default:
break;
}
}
}
private void Start()
{
mainCamera = Camera.main;
cinemachineBrain = mainCamera.GetComponent<CinemachineBrain>();
liveVirtualCamera = cinemachineBrain.ActiveVirtualCamera;
cinemachineBrain.m_CameraActivatedEvent.AddListener(OnCameraActivated);
}
private void Update()
{
if (isTransitioning && !cinemachineBrain.IsBlending)
{
isTransitioning = false;
OnTransitionComplete();
}
}
private void OnCameraActivated(ICinemachineCamera fromCam, ICinemachineCamera toCam)
{
SetCameraScriptsActive(fromVirtualCamera, false);
liveVirtualCamera = toCam;
isTransitioning = true;
Debug.Log("Camera Activated");
}
private void OnTransitionComplete()
{
SetCameraScriptsActive(liveVirtualCamera, true);
Debug.Log("Transition Complete");
}
}
As far as I know, CameraActivatedEvent passes two parameters to my listener, witch are both ICinemachineCamera. But why is there an issue when I’m using them with my method?
And I’ll provide MainCameraScript if needed:
using System.Collections;
using UnityEngine;
using Cinemachine;
public class MainCameraScript : MonoBehaviour
{
[Header("Camera Movement Keybindings")]
public KeyCode moveUp = KeyCode.W;
public KeyCode moveDown = KeyCode.S;
public KeyCode moveLeft = KeyCode.A;
public KeyCode moveRight = KeyCode.D;
[Header("Camera Movement Settings")]
public float cameraMovementSpeed = 20.0f;
[Header("Camera Rotation Keybindings")]
public KeyCode rotateLeft = KeyCode.Q;
public KeyCode rotateRight = KeyCode.E;
[Header("Camera Rotation Settings")]
public float rotationTime = 0.5f;
[Header("Camera Zoom Settings")]
public float cameraZoomSpeed = 10.0f;
public float minimumZoomDistance = 0.0f;
public float maximumZoomDistance = 10.0f;
[Header("Camera Clamp Settings")]
public float cameraClampBorder = 5.0f;
private CinemachineVirtualCameraBase virtualCamera;
private bool isRotating = false;
private float currentZoom = 0.0f;
private void Awake()
{
virtualCamera = GetComponent<CinemachineVirtualCameraBase>();
}
private IEnumerator RotateCamera(Transform cameraTransform, float angle)
{
isRotating = true;
Quaternion currentRotation = cameraTransform.rotation;
Quaternion targetRotation = Quaternion.Euler(currentRotation.eulerAngles.x, currentRotation.eulerAngles.y + angle, currentRotation.eulerAngles.z);
float currentTime = 0.0f;
while (currentTime < rotationTime)
{
currentTime += Time.deltaTime;
Quaternion newRotation = Quaternion.Lerp(currentRotation, targetRotation, currentTime / rotationTime);
cameraTransform.rotation = newRotation;
yield return null;
}
isRotating = false;
}
private void MoveCamera(Transform cameraTransform, DirectionType direction)
{
Vector3 currentRotation = cameraTransform.rotation.eulerAngles;
Vector3 currentPosition = cameraTransform.position;
currentRotation.x = 0.0f;
Quaternion cachedRotation = Quaternion.Euler(currentRotation);
Vector3 movement = Vector3.zero;
float movementSpeed = cameraMovementSpeed * Time.deltaTime;
switch (direction)
{
case DirectionType.Forward:
movement = cachedRotation * Vector3.forward * movementSpeed;
break;
case DirectionType.Backward:
movement = cachedRotation * Vector3.back * movementSpeed;
break;
case DirectionType.Left:
movement = cachedRotation * Vector3.left * movementSpeed;
break;
case DirectionType.Right:
movement = cachedRotation * Vector3.right * movementSpeed;
break;
}
cameraTransform.position = currentPosition + movement;
}
private void ZoomCamera(Transform cameraTransform, float zoom)
{
float zoomAmount = zoom * cameraZoomSpeed;
float newZoom = currentZoom + zoomAmount;
newZoom = Mathf.Clamp(newZoom, minimumZoomDistance, maximumZoomDistance);
zoomAmount = newZoom - currentZoom;
Vector3 newCameraPosition = cameraTransform.position + cameraTransform.forward * zoomAmount;
cameraTransform.position = newCameraPosition;
currentZoom = newZoom;
}
private void Update()
{
Transform cameraTransform = this.transform;
if (Input.GetKey(moveUp))
{
MoveCamera(cameraTransform, DirectionType.Forward);
}
if (Input.GetKey(moveDown))
{
MoveCamera(cameraTransform, DirectionType.Backward);
}
if (Input.GetKey(moveLeft))
{
MoveCamera(cameraTransform, DirectionType.Left);
}
if (Input.GetKey(moveRight))
{
MoveCamera(cameraTransform, DirectionType.Right);
}
if (!isRotating)
{
if (Input.GetKeyDown(rotateLeft))
{
StartCoroutine(RotateCamera(cameraTransform, -90.0f));
}
if (Input.GetKeyDown(rotateRight))
{
StartCoroutine(RotateCamera(cameraTransform, 90.0f));
}
float zoom = Input.GetAxis("Mouse ScrollWheel");
if (zoom != 0.0f)
{
ZoomCamera(cameraTransform, zoom);
}
}
}
}
Thanks for help!