Multiple units to focus

Hello everyone! i’m struggling with Cinemachine.
I have a Board in which i can place units.
I have a Main Camera with a brain attached to it.
I need to focus an unit when the user presses double click.

var clickStream = this.OnMouseDownAsObservable();
            clickStream.Buffer(clickStream.Throttle(TimeSpan.FromSeconds(0.2f)))
                .Where(x => x.Count >= 2)
                .Subscribe(_ => FocusUnit());

And must lose the focus when the player presses another double clic on it. Or hit Escape.
If you’re focusing an unit and you double click another, then the focus passes to the other unit.
Every unit has a FreeLook camera attached to it.

I have this Focusable.cs script attached to every unit

public class Focusable : MonoBehaviour
    {
        private CameraMaster cameraMaster { get { return Camera.main.GetComponent<CameraMaster>(); } }
        private bool _selected = false;
        private bool isHome;
        private bool isPreparation;

        [SerializeField]
        public CinemachineFreeLook personalCamera;
        void Start()
        {
            var clickStream = this.OnMouseDownAsObservable();
            clickStream.Buffer(clickStream.Throttle(TimeSpan.FromSeconds(0.2f)))
                .Where(x => x.Count >= 2)
                .Subscribe(_ => FocusUnit());
            var escape = this.UpdateAsObservable()
            .Where(_ => Input.GetKeyDown(KeyCode.Escape))
            .Subscribe(_ =>
            {
                _selected = false;
                cameraMaster.ReleaseCamera();
            });
            NetworkEventListener.Instance.PhaseInfoStream.Subscribe(e =>
            {
                isPreparation = e.phase == Phase.Preparation;
            });

        }

        void FocusUnit()
        {
            if (!_selected)
            {
                _selected = true;
                personalCamera.GetComponent<CinemachineFreeLook>().m_Heading.m_Bias = (GetComponent<UnitController>().IsHome || isPreparation) ? 0 : 180;//giro la cámara
                cameraMaster.SetLiveCamera(personalCamera);
            }
            else
            {
                _selected = false;
                cameraMaster.ReleaseCamera();
            }
        }
    }

And CameraMaster.cs is my way of doing that, but this is not the way to do it right.

public class CameraMaster : MonoBehaviour
{
    private ICinemachineCamera _defaultCamera;
    private bool isInit = false;
    public ICinemachineCamera LiveCamera;
    private Queue<ICinemachineCamera> cameraQueue;
    private void Awake()
    {
        cameraQueue = new Queue<ICinemachineCamera>();
    }
    public void Init(ICinemachineCamera defaultCamera)
    {
        if (!isInit)
        {
            _defaultCamera = defaultCamera;
            SetLiveCamera(defaultCamera);
        }
        isInit = true;
    }
    public void SetLiveCamera(ICinemachineCamera camera)
    {
        if (LiveCamera != null)
        {
            cameraQueue.Enqueue(LiveCamera);
            LiveCamera.Priority = 0;
        }
        LiveCamera = camera;
        LiveCamera.Priority = int.MaxValue;
    }

    public void ReleaseCamera()
    {
        if (cameraQueue.Count > 1)
        {
            LiveCamera.Priority = 0;
            LiveCamera = cameraQueue.Dequeue();
        }
        if (cameraQueue.Count == 1)
        {
            _defaultCamera.Priority = int.MaxValue;
            LiveCamera = _defaultCamera;
        }
    }

I didn’t find any solutions online or in the documentation, i’ve also tried enabling/disablig virtual cameras but it doesn’t work. What i am doing wrong?

CameraMaster is attached to the main camera

For performance, you should have all the FreeLooks deactivated except the current one. Leave them all at the default priority (e.g. 10).

You don’t need the CameraMaster script at all. The Cinemachine brain can blend from a FreeLook even when the FreeLook is deactivated, so your camera switching code can be very simple. Something like this:

void SetLiveCamera(ICinemachineCamera vcam)
{
    var brain = CinemachineCore.Instance.GetActiveBrain(0);
    if (brain.ActiveVirtualCamera != null)
        brain.ActiveVirtualCamera.VirtualCameraGameObject.SetActive(false);
    vcam.VirtualCameraGameObject.SetActive(true);
}
1 Like

Thank you so much!!!