Search Unity

Avoid Cinemachine collider returning after obstacle moved

Discussion in 'Cinemachine' started by argh6543, Jan 28, 2021.

  1. argh6543

    argh6543

    Joined:
    Apr 14, 2017
    Posts:
    48
    I currently use Cinemachine to follow the player object through a scene. Everything works well except the collider. When something blocks the view of the player, the camera moves to avoid it, just as expected. I use preserve camera distance, so the camera pans to a better angle. So far so good. However, when the interfering object moves on, the camera moves back to it's previous location. How do I disable this return? If the other view is equally valid, then I'd rather keep the camera at the new position than move it back.
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,730
    There's no logic built-in for that. I suppose you could write a script that polls the collider, deduces the offset it applies, then pushes it back to the follow behaviour in the vcam.
     
  3. argh6543

    argh6543

    Joined:
    Apr 14, 2017
    Posts:
    48
    Thank you for the quick answer!

    I'm a bit surprised - I figured this would be others have asked for before. Is there something that is similar to what I'm asking?
     
  4. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,730
    Nobody has ever asked this before!

    I confess it seems a little strange to me. You just want the collider to push the camera and leave it there? Nobody ever pushes it back unless the camera happens to collide with something that does?

    Could you post an image of the situation, so I can get a better sense of what you're trying to do?
     
  5. argh6543

    argh6543

    Joined:
    Apr 14, 2017
    Posts:
    48
    I put together a quick scene (http://47.206.76.71/test.zip). Load and start the scene. You'll see the player object moving away from the camera at a steady speed. The camera is set to follow and does so properly. After a few seconds, activate the Obstacle game object. It blocks the player and the camera properly moves forward. So far so good.

    However, when you deactivate the obstacle again, the camera snaps back to the normal follow distance. What I'm trying to achieve is that the camera stays in the position it took during resolving the collision and lets the player move away until it reaches the normal follow distance.
     
  6. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,730
    Thanks for the scene. It helps me to understand.

    As I mentioned, you can write a custom script to dynamically adjust the Transposer's follow distance, to keep it within a desired range. Here is a simple script that does that. Drop it in your project and add it to the virtual camera using the Extensions dropdown in the vcam inspector. It's hardcoded to expect a vcam with a Transposer in SimpleFollow mode, like the one in your example scene, but if you need it to work on different kinds of vcams you can modify it accordingly.

    Code (CSharp):
    1. using Cinemachine;
    2. using UnityEngine;
    3.  
    4. [AddComponentMenu("")] // Hide in menu
    5. [SaveDuringPlay]
    6. public class FollowDistanceDeadZone : CinemachineExtension
    7. {
    8.     [Tooltip("Keep the Follow distance within this range")]
    9.     public float MaxDistance = 10;
    10.  
    11.     CinemachineTransposer Transposer;
    12.  
    13.     protected override void OnEnable()
    14.     {
    15.         base.OnEnable();
    16.         var vcam = VirtualCamera as CinemachineVirtualCamera;
    17.         Transposer = vcam?.GetCinemachineComponent<CinemachineTransposer>();
    18.     }
    19.  
    20.     protected override void PostPipelineStageCallback(
    21.         CinemachineVirtualCameraBase vcam,
    22.         CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
    23.     {
    24.         if (stage == CinemachineCore.Stage.Finalize)
    25.         {
    26.             var follow = vcam.Follow;
    27.             if (follow != null && Transposer != null)
    28.             {
    29.                 var targetPos = follow.position;
    30.                 var camPos = state.FinalPosition;
    31.                 targetPos.y = camPos.y = 0;
    32.                 var currentDistance = Vector3.Distance(camPos, targetPos);
    33.                 Transposer.m_FollowOffset.z = -Mathf.Min(currentDistance, MaxDistance);
    34.             }
    35.         }
    36.     }
    37. }
    Note: the code above is a little naive - for example, it doesn't implement a "MinDistance" (what if the player turns around and starts walking towards the camera?) - but I think it's enough to illustrate the principle.
     
    Last edited: Jan 30, 2021
    argh6543 likes this.
  7. argh6543

    argh6543

    Joined:
    Apr 14, 2017
    Posts:
    48
    Thank you! I can't say I quite understand the code snippet yet, but that gives me something to do next week :)
     
    Gregoryl likes this.
  8. argh6543

    argh6543

    Joined:
    Apr 14, 2017
    Posts:
    48
    I got my problem fixed I think - all thanks to your great help and code example. You're amazing and I wish Unity had more people with both your level of knowledge and the time to give such well thought out answers and help.

    You are an amazing resource!
     
    Gregoryl likes this.