Quick answer: You are probably using CinemachineConfiner (3D) on a 2D camera, or the Bounding Shape 2D reference is null. Use CinemachineConfiner2D for 2D games, assign a PolygonCollider2D or CompositeCollider2D, and call InvalidatePathCache() after changing the shape.
Here is how to fix Cinemachine Confiner failing to keep the camera in bounds. You set up a bounding polygon, dragged it into the Confiner extension, and pressed Play. The camera happily wanders outside the bounds, showing the black void beyond your level. The extension is there, the shape is assigned, nothing logs an error. Confiner is one of Cinemachine’s most-used extensions, and it is also one of the most commonly misconfigured.
The Symptom
Your CM Virtual Camera follows a target. A CinemachineConfiner or CinemachineConfiner2D is attached as an extension. You see one of:
- Camera leaves the bounding shape freely, ignoring it completely
- Camera is clamped but edges show pixels outside bounds (tilemap black)
- Works in Edit Mode preview, fails in Play Mode
- Worked when you set it up, stopped working after reassigning the shape
What Causes This
Wrong extension for the project dimension. Cinemachine ships two confiners: CinemachineConfiner (the original, uses 3D or 2D colliders but not camera-aware) and CinemachineConfiner2D (2D-specific, camera-aware). The original confiner only confines the camera’s position, not its view rectangle. In a 2D game, that means the camera center stays inside the bounds but the edges show outside it.
Bounding Shape reference null. Cinemachine does not log an error when the Bounding Shape 2D field is empty. The extension silently does nothing. If you reassigned the scene’s bounding polygon and forgot to drag it back in, the confiner stops working.
Disabled GameObject. If the bounding shape is on a GameObject that is inactive at Start, the confiner’s cache is built from a shape with zero points and the camera roams freely.
Stale path cache. The 2D confiner precomputes an “inner polygon” that the camera center must stay inside, based on the current orthographic size. If you change orthographic size (zoom), the cache becomes wrong. If you swap the bounding shape at runtime, the cache is stale.
Damping overshoot. Even with the confiner working, high damping values on the virtual camera (Body > Damping X/Y/Z) let the camera lag behind for tens of frames. During that lag, the camera is outside bounds. The confiner corrects it — but visually the camera briefly showed out-of-bounds content.
The Fix
Step 1: Use CinemachineConfiner2D for 2D games. On your CM Virtual Camera, click Add Extension and choose CinemachineConfiner2D (not the older CinemachineConfiner). If you already have the old one, remove it.
Create an empty GameObject, attach a PolygonCollider2D, edit its shape to cover your playable area. Drag that GameObject into the Bounding Shape 2D field.
using Cinemachine;
using UnityEngine;
public class ConfinerSetup : MonoBehaviour
{
[SerializeField] private CinemachineVirtualCamera vcam;
[SerializeField] private PolygonCollider2D bounds;
void Awake()
{
var confiner = vcam.GetComponent<CinemachineConfiner2D>();
confiner.m_BoundingShape2D = bounds;
confiner.InvalidatePathCache();
}
}
Step 2: Assign the bounding shape explicitly. Do not rely on the shape surviving scene saves — Unity sometimes breaks PolygonCollider2D references across prefab edits. Either set in code at Start or verify via OnValidate.
Step 3: Invalidate cache after changes. Any change to the shape (number of points, vertex positions, camera orthographic size) requires a cache rebuild:
confiner.InvalidatePathCache();
Call this after zooming in/out, after swapping bounding shapes between scenes, and after editing the polygon at runtime. Without it, the confiner uses the old polygon and the camera appears to ignore changes.
Step 4: Tune damping to prevent overshoot. On the CM Virtual Camera, under Body (Framing Transposer or similar), set Damping values to 0.5 or lower during combat/action scenes. High damping (2+) looks cinematic but lets the camera wander visibly outside bounds before being pulled back.
For exploration cameras where gentle motion matters, keep damping high but enlarge the bounding shape so the damping lag happens within the bounds.
3D Games With Camera Colliders
For 3D, use CinemachineConfiner with a Collider (box, sphere, or mesh) as Bounding Volume. Mesh colliders must be convex. The 3D confiner does not precompute an inner volume — it clamps the camera position to the collider surface. That means camera rotation plus the view frustum can still show content outside the volume. Shrink the volume to leave visual margin.
[SerializeField] private CinemachineConfiner confiner3D;
[SerializeField] private Collider boundsCollider;
void Start()
{
confiner3D.m_BoundingVolume = boundsCollider;
confiner3D.InvalidatePathCache();
}
Debugging
Enable Gizmos in Game View. The confiner draws its bounding shape (or computed inner polygon for 2D) as a green line. If you see no line, the shape is null or the GameObject is inactive. If the line is smaller than you expect, the 2D confiner shrunk it based on orthographic size — that is the “safe” zone for the camera center, and it is correct.
For live inspection:
void OnDrawGizmos()
{
if (confiner.m_BoundingShape2D == null) Debug.LogWarning("Confiner has no bounds!");
}
“The confiner is only as good as its bounding shape reference. Missing reference, no confine. Stale cache, wrong confine.”
Runtime Shape Swaps
For games with multiple rooms or zones, swap the bounding shape when the player crosses a door trigger:
public void SetZone(PolygonCollider2D newZone)
{
confiner.m_BoundingShape2D = newZone;
confiner.InvalidatePathCache();
}
Always pair the assignment with InvalidatePathCache. Otherwise the camera continues to use the previous zone’s shape.
Confiner2D for 2D. Assign the shape. Invalidate the cache. Tune damping.