Search Unity

Follow only along a certain axis

Discussion in 'Cinemachine' started by Devilly, Aug 9, 2018.

  1. Devilly

    Devilly

    Joined:
    Dec 5, 2017
    Posts:
    14
    I have a Cinemachine Virtual Camera which follows the player nicely according to the Follow property and the settings in the Body. Now what I'd like is to make the cinemachine follow only along a certain axis. I'm assuming there is a setting for this?
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    There is no specific setting for that, but it's very easy to write an extension that constrains the camera's position. Here is an example that constrains it to a plane at constant Z. You can modify it to constrain the camera position to a line. Just drop the file into your assets, and it will be available in the vcam's "Extensions" dropdown.
    Code (CSharp):
    1. using UnityEngine;
    2. using Cinemachine;
    3.  
    4. /// <summary>
    5. /// An add-on module for Cinemachine Virtual Camera that locks the camera's Z co-ordinate
    6. /// </summary>
    7. [ExecuteInEditMode] [SaveDuringPlay] [AddComponentMenu("")] // Hide in menu
    8. public class LockCameraZ : CinemachineExtension
    9. {
    10.     [Tooltip("Lock the camera's Z position to this value")]
    11.     public float m_ZPosition = 10;
    12.  
    13.     protected override void PostPipelineStageCallback(
    14.         CinemachineVirtualCameraBase vcam,
    15.         CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
    16.     {
    17.         if (stage == CinemachineCore.Stage.Body)
    18.         {
    19.             var pos = state.RawPosition;
    20.             pos.z = m_ZPosition;
    21.             state.RawPosition = pos;
    22.         }
    23.     }
    24. }
    25.  
     
  3. Devilly

    Devilly

    Joined:
    Dec 5, 2017
    Posts:
    14
    That's working nicely. Thank you!
     
  4. Devilly

    Devilly

    Joined:
    Dec 5, 2017
    Posts:
    14
    There is one thing, though. Implementing it this way causes blending between two camera's to be somewhat hard, doesn't it? What I want is several y values on which the player is tracked. If the player moves from being the closest to value A to being the closest to value B the camera should gradually move to the other y value. Is this doable with Cinemachine or do I have to write such code myself?
     
  5. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    I don't see why the blending should be hard. The camera will blend from one track to the other when you activate the new vcam. You can set the blend style in the Brain.
     
  6. Devilly

    Devilly

    Joined:
    Dec 5, 2017
    Posts:
    14
    I had this blending set up and it worked fine. Now, when setting the y value of the cameras in the extension class it jumps straight to the y value of the activated camera.
     
  7. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    Blending should still work. Can you show me inspectors and code?
     
  8. Devilly

    Devilly

    Joined:
    Dec 5, 2017
    Posts:
    14
    I was investigating this stuff based on your comment. I applied quite some changes in a small time frame to our project. It seems the problem lies in one of the other changes. Once I get to the bottom of this I'll let you know if everything works as you're suggesting. Thanks. :)
     
    Gregoryl likes this.
  9. Devilly

    Devilly

    Joined:
    Dec 5, 2017
    Posts:
    14
    After some fiddling around I found out the cause for the missing blend was I destroyed the virtual camera a blend started with too early.

    So you've helped me perfectly. Thank you!
     
    Zamaroht and Gregoryl like this.
  10. ben4d85

    ben4d85

    Joined:
    Dec 26, 2018
    Posts:
    47
    I've been trying out this script and just wanted to leave this note here in case anybody else is facing the same questions I did!

    Why doesn't this script work?
    If you are using a Framing Transposer, you need to change the code as described here:
    https://forum.unity.com/threads/cinemachine-follow-player-lock-axis.937118/

    Is it possible to combine this script with the "Cinemachine Confiner" extension?
    Yes, works like a charm!
     
    Last edited: Feb 22, 2021
    Zamaroht and Gregoryl like this.
  11. codexin

    codexin

    Joined:
    Apr 4, 2018
    Posts:
    4
    Thank you I used it for locking in x axis and it works very well.
     
    Gregoryl likes this.
  12. CrabStag

    CrabStag

    Joined:
    Aug 7, 2021
    Posts:
    1

    This works great! However, every time i close and re-open my project, it gives me the following error " the referenced script on this behavior is missing"
    When I re-add the extension to vcam it's solved again, until the next restart of my project.
    Anyone have any idea how to fix this?
     
  13. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    I don't think that's caused by the custom extension. Try re-importing the project. If that doesn't solve it, see if you can isolate the problem in a small scene that you can send me.
     
  14. jrbarcha

    jrbarcha

    Joined:
    Jun 24, 2015
    Posts:
    3
    its working great. Thank you very much
     
    Gregoryl likes this.
  15. Kokowolo

    Kokowolo

    Joined:
    Mar 26, 2020
    Posts:
    60
    Thanks Gregoryl! Here's also a general script for any axis direction where the lockPositionValue is offset by either the virtual camera's Follow transform or the world origin.
    Code (CSharp):
    1. using UnityEngine;
    2. using Cinemachine;
    3.  
    4. [AddComponentMenu("")] // Hide in menu
    5. [SaveDuringPlay]
    6. [ExecuteInEditMode]
    7. public class LockCameraExtension : CinemachineExtension
    8. {
    9.     protected enum LockDirection
    10.     {
    11.         X,
    12.         Y,
    13.         Z
    14.     }
    15.  
    16.     [Header("Settings")]
    17.     [Tooltip("direction to lock the camera's position")]
    18.     [SerializeField] LockDirection lockDirection = LockDirection.Z;
    19.     [Tooltip("lock the camera's position to this value")]
    20.     public float lockPositionValue = 10;
    21.     [Tooltip("whether the lockPositionValue's origin is the VCam's follow transform")]
    22.     [SerializeField] bool useVCamFollowAsOrigin;
    23.  
    24.     protected override void PostPipelineStageCallback(
    25.         CinemachineVirtualCameraBase vcam, CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
    26.     {
    27.         if (stage != CinemachineCore.Stage.Body) return;
    28.        
    29.         Vector3 pos = state.RawPosition;
    30.         Vector3 lockPosition = (useVCamFollowAsOrigin && vcam.Follow ? vcam.Follow.position : Vector3.zero) +
    31.             Vector3.one * lockPositionValue;
    32.        
    33.         state.RawPosition = lockDirection switch
    34.         {
    35.             LockDirection.X => new Vector3(lockPosition.x, pos.y, pos.z),
    36.             LockDirection.Y => new Vector3(pos.x, lockPosition.y, pos.z),
    37.             LockDirection.Z => new Vector3(pos.x, pos.y, lockPosition.z),
    38.             _ => throw new System.NotImplementedException()
    39.         };
    40.     }
    41. }
     
    Last edited: Apr 6, 2024
    Mushakushi likes this.