Help with Cinemachine 2D Confiner

Hi all

New to Unity and fairly new to coding generally. I’ve been following Sasquatch B’s tutorial on metroidvania camera controls (

) and have an issue I’m struggling to resolve.

I’ve built the camera system, which creates a Cinemachine Virtual Camera following an object which in turn follows the player (for smoother movement). My Camera works great, but will NOT stay within the bounds of a 2D confiner. I’ve tried both Cinemachine Confiner and Cinemachine Confiner 2D, tried Box and Polygon colliders etc. - no joy.

I suspect that the issue is that the code I use to move the Camera (i.e. follow the object following the player) is overriding the confiner bounds. Any idea how to solve this issue?

For reference, this is my CameraManager script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cinemachine;

public class CameraManager : MonoBehaviour
{
    public static CameraManager instance;

    [SerializeField] private CinemachineVirtualCamera[] _allVirtualCameras;

    [Header("Controls for lerping the Y Damping during player jump/fall")]
    [SerializeField] private float _fallPanAmount = 0.25f;
    [SerializeField] private float _fallYPanTime = 0.35f;
    public float _fallSpeedYDampingChangeThreshold = -15f;

    public bool IsLerpingYDamping { get; private set; }
    public bool LerpedFromPlayerFalling { get; set; }

    private Coroutine _lerpYPanCoroutine;
    private Coroutine _panCameraCoroutine; // Coroutine to run in our CameraTrigger script to auto pan the camera.

    private CinemachineVirtualCamera _currentCamera;
    private CinemachineFramingTransposer _framingTransposer;

    private float _normYPanAmount;

    private Vector3 _startingTrackedObjectOffset;

    private void Awake()
    {
        if (instance == null)
        {
            instance = this;
        }

        for (int i = 0; i < _allVirtualCameras.Length; i++)
        {
            if (_allVirtualCameras[i].enabled)
            {
                // Set current active camera
                _currentCamera = _allVirtualCameras[i];

                // Set the framing transposer
                _framingTransposer = _currentCamera.GetCinemachineComponent<CinemachineFramingTransposer>();
            }
        }

        // Set the YDamping amount based on the inspector value
        _normYPanAmount = _framingTransposer.m_YDamping;

        // Set the starting position of the tracked object offset
        _startingTrackedObjectOffset = _framingTransposer.m_TrackedObjectOffset;
    }

    // Pan the Camera
    public void PanCameraOnContact(float panDistance, float panTime, PanDirection panDirection, bool panToStartingPos)
    {
        _panCameraCoroutine = StartCoroutine(PanCamera(panDistance, panTime, panDirection, panToStartingPos));
    }

    private IEnumerator PanCamera(float panDistance, float panTime, PanDirection panDirection, bool panToStartingPos)
    {
        Vector3 endPos = Vector3.zero;
        Vector3 startingPos = Vector3.zero;

        // Handle pan from trigger
        if (!panToStartingPos)
        {
            // Set the direction and distance
            switch (panDirection)
            {
                case PanDirection.Up:
                    endPos = Vector3.up;
                    break;
                case PanDirection.Down:
                    endPos = Vector3.down;
                    break;
                case PanDirection.Left:
                    endPos = Vector3.left;
                    break;
                case PanDirection.Right:
                    endPos = Vector3.right;
                    break;
                default:
                    break;
            }

            endPos *= panDistance;

            startingPos = _startingTrackedObjectOffset;

            endPos += startingPos;
        }
        // Handle the pan back to the starting position
        else
        {
            startingPos = _framingTransposer.m_TrackedObjectOffset;
            endPos = _startingTrackedObjectOffset;
        }

        // Handle the actual panning of the camera
        float elapsedTime = 0f;
        while (elapsedTime < panTime)
        {
            elapsedTime += Time.deltaTime;

            Vector3 panLerp = Vector3.Lerp(startingPos, endPos, (elapsedTime / panTime));
            _framingTransposer.m_TrackedObjectOffset = panLerp;

            yield return null;
        }
    }

    public void LerpYDamping(bool isPlayerFalling)
    {
        if (_lerpYPanCoroutine != null)
        {
            StopCoroutine(_lerpYPanCoroutine);
        }

        _lerpYPanCoroutine = StartCoroutine(LerpYAction(isPlayerFalling));
    }

    public IEnumerator LerpYAction(bool isPlayerFalling)
    {
        IsLerpingYDamping = true;

        // Grab the starting damping
        float startDampAmount = _framingTransposer.m_YDamping;
        float endDampAmount = 0f;

        // Determine end damping amount
        if (isPlayerFalling)
        {
            endDampAmount = _fallPanAmount;
            LerpedFromPlayerFalling = true;
        }
        else
        {
            endDampAmount = _normYPanAmount;
        }

        // Lerp the pan amount
        float elapsedTime = 0f;
        while (elapsedTime < _fallYPanTime)
        {
            elapsedTime += Time.deltaTime;
            float lerpedPanAmount = Mathf.Lerp(startDampAmount, endDampAmount, (elapsedTime / _fallYPanTime));
            _framingTransposer.m_YDamping = lerpedPanAmount;

            yield return null;
        }

        _framingTransposer.m_YDamping = endDampAmount;
        IsLerpingYDamping = false;
    }
}

I’ll move your post to the Cinemachine forum. I’ll also remove the 2D physics tag as it’s not related to your post.

@Jwhitehead Some questions.

  • What happens when you disable your camera manager script?
  • Can you show an image of the vcam inspector?
  • Can you also show the scene hierarchy? I want to understand the relationship between main camera, vcam, target, and camera bounds shape.
  • What version of CM are you using?
  • Can you show an image or a video of the problem?