Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Unrelaible results using cinemachine confiner with group framing transposer

Discussion in 'Cinemachine' started by SudoCat, Sep 9, 2023.

  1. SudoCat

    SudoCat

    Joined:
    Feb 19, 2013
    Posts:
    45
    I'm working on a 2D project with local multiplayer. We need to keep all players on screen at the same time, and keep the camera confined to the boundaries of the arena. When players are close together, zoom the camera in, when they're further apart, zoom farther out.

    This seems like it should be a fairly straight forward requirement to solve with Cinemachine; Just use a Target Group, a Framing Transposer, and a Confiner extension on the vcam.

    Except I've never been able to make this work. I've mostly ended up ditching the confiner part of this setup, because as far as I can tell, it does not work with the Confiner. I've tried using both the Confiner in Confine 2D mode, and the Confiner 2D extension. We have a simple Camera Bounds polygon, set to a 16:9 aspect ratio.
    The framing transposer is configured to never let the camera frustum grow larger than this camera bounds size. I've attempted using the oversize window property of the Confiner 2D script, with a broad range of settings.

    Unfortunately, even with all of this, the results are unreliable, and often worse than having no confiner at all.

    From what I can gather, the confiner only works with cameras that have a fixed zoom level. We have a perspective camera setup that uses both dolly and zoom, although in the past I've tried with either only dolly or zoom, and using orthographic camera too.

    The issues we observe is that the camera confiner only seems to work at the size the cache was baked for. If I test in editor by manually baking the cache and moving the player around, it will work perfectly, until the camera zoom adjusts, and then the results become unreliable again; either extending the viewable area beyond the camera bounds, or constraining the camera too tightly, causing players to be off screen.

    Obviously it would be a terrible idea to keep calling invalidate cache every time the zoom changes, which is the only answer I've found to make things work. It was better to simply remove the confiner.

    We even have a custom target group script, that prevents out target group bounding box from exceeding the size of the CameraBounds, and an offscreen camera solution, which again, helps the problem, but doesn't always prevent the camera escaping the bounds in extreme scenarios, revealing the seams beyond the level.

    I've read just about every thread in this forum looking for answers, but always come up short. I've tried implementing custom confiner scripts, but usually found myself sorely out of my depth.

    So I'm finally at my wits end, and I'm here to ask for help. Am I misunderstanding how this feature is supposed to be used, or is this just not possible with Cinemachine? Is there something on the asset store that may save me? (In previous projects I've used ProCamera2D, which did not seem to encounter these issues, although it's been years since I used it)

    How should I proceed?

    Thanks in advance!
     
  2. Unifikation

    Unifikation

    Joined:
    Jan 4, 2023
    Posts:
    1,043
    Here to say I've had similar experiences and ended up making preset cameras for each possible situation and then blending between them with complex yet judicious use of the Cinemachine Mixer's functionality. Despite great care it's not ideal, and gets very messy with 3 or more possible camera situations.

    Here's hoping discussions in this thread reveal a way to reliably use confiners and group framing.
     
    SudoCat likes this.
  3. SudoCat

    SudoCat

    Joined:
    Feb 19, 2013
    Posts:
    45
    Glad to know I'm not the only one battling with this at least.

    The part that confuses me the most is what reads like conflicting information in the documentation

    "When confining the camera, the Cinemachine Confiner 2D considers the camera’s view size at the polygon plane, and its aspect ratio. Based on this information and the input polygon, it computes a second (smaller) polygon, and constrains the camera’s transform to it. Computation of this secondary polygon is resource-intensive, so you should only do this when absolutely necessary."

    This definitely seems to imply that Confiner 2D functions with a fixed camera size, and that changes to the camera view size will require recalculation, yet...

    "set the Max Window Size property to the largest size you expect the camera window to have."​

    this statement seems to imply that the window size could be variable, which would surely mean the camera size could be variable?

    The source code for the CinemachineConfiner2D also seems to check the frustum height each frame, and convert it to the baked space - this made me think that it should be adjusting to frustum size, but then it doesn't seem to actually do any comparisons to previous frustum sizes.

    Code (CSharp):
    1. var currentFrustumHeight = CalculateHalfFrustumHeight(state, cameraPosLocal.z);
    2. // convert frustum height from world to baked space. deltaWorldToBaked.lossyScale is always uniform.
    3. var bakedSpaceFrustumHeight = currentFrustumHeight * m_shapeCache.m_DeltaWorldToBaked.lossyScale.x;
    4.  
    5. // Make sure we have a solution for our current frustum size
    6. var extra = GetExtraState<VcamExtraState>(vcam);
    7. extra.m_vcam = vcam;
    8. if (confinerStateChanged || extra.m_BakedSolution == null || !extra.m_BakedSolution.IsValid())
    9. {
    10.     extra.m_BakedSolution = m_shapeCache.m_confinerOven.GetBakedSolution(bakedSpaceFrustumHeight);
    11. }
    If this is simply a limitation of the confiner, I feel like this should be clearly stated on the documentation, at the very least. Ideally, it'd be great to be presented with an alternative solution.
     
  4. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,233
    The confiner does indeed bake for a specific frustum height. If you change that height dynamically, then you must re-bake the confiner (calling InvalidateCache is the way to do that). We don't do it automatically because of the performance implications.
     
  5. SudoCat

    SudoCat

    Joined:
    Feb 19, 2013
    Posts:
    45
    Thanks for the clarification, it would be great if the documentation clearly stated this, and perhaps offered some alternatives - I imagine this must be a fairly common requirement. However, I recognise that probably isn't going to be a priority.

    In the end I created my own custom, much dumber confiner, which is working much better for my use case, without taking the perf hit of baking a bunch of specifics I don't need.
     
    antoinecharton likes this.
  6. antoinecharton

    antoinecharton

    Unity Technologies

    Joined:
    Jul 22, 2020
    Posts:
    156
    SudoCat likes this.
  7. SudoCat

    SudoCat

    Joined:
    Feb 19, 2013
    Posts:
    45
    This is great to see!

    This section in particular clearly describes the issue.

    My only suggestion would be adding a note either below this, or possibly better in the Efficiency section, highlighting that due to the expense of repeatedly invalidating the lens cache, this confiner is not suitable for cameras which change zoom, size or field of view frequently per frame, such as when using the Group Framing Extension, so a custom confining solution is advised.
     
    antoinecharton likes this.