Search Unity

Constant speed on Dolly Track

Discussion in 'Cinemachine' started by gdv_unity, Aug 1, 2017.

  1. gdv_unity

    gdv_unity

    Joined:
    Sep 10, 2014
    Posts:
    4
    Hey guys,

    I'm trying to move the camera with constant speed on a dolly track.
    I managed to calculate the length of the segments between two waypoints and animate the "Path Position" value based on that.
    What I noticed is that when the camera is approaching the next waypoint, it slows down a bit.
    All the damping values are set to 0. Am I missing something? Is there a way to bypass the easing?

    Thanks for your help. :)
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
  3. gdv_unity

    gdv_unity

    Joined:
    Sep 10, 2014
    Posts:
    4
    Hi Gregoryl,

    Thanks for your quick reply!
    See my test script below.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Cinemachine;
    5. using UnityEditor;
    6.  
    7. public class MoveCameraTest : MonoBehaviour {
    8.  
    9.     public CinemachineVirtualCamera virtualCamera;
    10.     public CinemachinePath path;
    11.     public AnimationCurve curve;
    12.     public float runningTime;
    13.     public float totalDuration;
    14.     public float currentPercentage;
    15.  
    16.     private CinemachineTrackedDolly dolly;
    17.     private float pathLength;
    18.  
    19.     private float[] pointPercentages;
    20.  
    21.     void Start(){
    22.         dolly = virtualCamera.GetCinemachineComponent<CinemachineTrackedDolly> ();
    23.  
    24.         pointPercentages = new float[path.m_Waypoints.Length + 1];
    25.         pointPercentages [0] = 0;
    26.         Keyframe keyframe = new Keyframe (0, 0);
    27.         curve.AddKey (keyframe);
    28.  
    29.         float length = 0;
    30.         float step = 1f / path.m_Appearance.steps;
    31.  
    32.         //Calculate total length of path
    33.         for (float t = path.MinPos + step; t <= path.MaxPos + step / 2; t += step) {
    34.             Vector3 prev = path.EvaluatePosition(t-step);
    35.             Vector3 p = path.EvaluatePosition(t);
    36.             length += Vector3.Distance (prev, p);
    37.         }
    38.  
    39.         pathLength = length;
    40.  
    41.         float partialLength = 0;
    42.         int counter = 0;
    43.         int currentStep = 0;
    44.         float currentPercentage = 0;
    45.  
    46.         //Build speed curve
    47.         for (float t = path.MinPos + step; t <= path.MaxPos + step / 2; t += step) {
    48.             Vector3 prev = path.EvaluatePosition(t-step);
    49.             Vector3 p = path.EvaluatePosition(t);
    50.             partialLength += Vector3.Distance (prev, p);
    51.             counter++;
    52.             if (path.m_Appearance.steps == counter) {
    53.                 currentStep = Mathf.RoundToInt (t);
    54.                 currentPercentage = (partialLength / pathLength);
    55.                 pointPercentages [currentStep] = currentPercentage;
    56.                 counter = 0;
    57.                 keyframe = new Keyframe (currentPercentage, currentStep);
    58.                 curve.AddKey (keyframe);
    59.             }
    60.         }
    61.  
    62.         for (int i = 0; i < curve.keys.Length; i++){
    63.             AnimationUtility.SetKeyLeftTangentMode (curve, i, AnimationUtility.TangentMode.Linear);
    64.             AnimationUtility.SetKeyRightTangentMode (curve, i, AnimationUtility.TangentMode.Linear);
    65.         }
    66.     }
    67.  
    68.     void Update(){
    69.         runningTime += Time.deltaTime;
    70.         currentPercentage = runningTime / totalDuration;
    71.  
    72.         if (runningTime >= totalDuration) {
    73.             runningTime -= totalDuration;
    74.         }
    75.         dolly.m_PathPosition = getPathPositionFromPercentage (currentPercentage);
    76.     }
    77.  
    78.     float getPathPositionFromPercentage(float perc){
    79.         return curve.Evaluate(perc);
    80.     }
    81. }
    82.  
     
  4. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    Your script was not sampling the path correctly. Try this instead:
    Code (CSharp):
    1. using UnityEngine;
    2. using Cinemachine;
    3. using UnityEditor;
    4.  
    5. public class MoveCameraTest : MonoBehaviour
    6. {
    7.     public CinemachineVirtualCamera virtualCamera;
    8.     public CinemachinePath path;
    9.     public AnimationCurve curve;
    10.     public float velocity;
    11.     public float currentDistance;
    12.  
    13.     private float pathLength;
    14.     private CinemachineTrackedDolly dolly;
    15.  
    16.     void SamplePath(int stepsPerSegment)
    17.     {
    18.         curve = new AnimationCurve();
    19.         float minPos = path.MinPos;
    20.         float maxPos = path.MaxPos;
    21.         float stepSize = 1f / Mathf.Max(1, stepsPerSegment);
    22.  
    23.         pathLength = 0;
    24.         Vector3 p0 = path.EvaluatePosition(0);
    25.         curve.AddKey(new Keyframe(0, 0));
    26.         for (float pos = minPos + stepSize; pos <( maxPos + stepSize/2); pos += stepSize)
    27.         {
    28.             Vector3 p = path.EvaluatePosition(pos);
    29.             pathLength += Vector3.Distance(p0, p);
    30.             curve.AddKey(new Keyframe(pathLength, pos));
    31.             p0 = p;
    32.         }
    33.  
    34.         for (int i = 0; i < curve.keys.Length; i++)
    35.         {
    36.             // TODO: replace this with something that does not depend on editor
    37.             AnimationUtility.SetKeyLeftTangentMode(curve, i, AnimationUtility.TangentMode.Linear);
    38.             AnimationUtility.SetKeyRightTangentMode(curve, i, AnimationUtility.TangentMode.Linear);
    39.         }
    40.     }
    41.        
    42.     void Start()
    43.     {
    44.         dolly = virtualCamera.GetCinemachineComponent<CinemachineTrackedDolly>();
    45.         if (path != null)
    46.             SamplePath(path.m_Appearance.steps); // TODO: decouple numSteps from appearance setting
    47.     }
    48.  
    49.     void Update()
    50.     {
    51.         int numKeys = (curve != null && curve.keys != null) ? curve.keys.Length : 0;
    52.         if (dolly != null && numKeys > 0 && pathLength > Vector3.kEpsilon)
    53.         {
    54.             currentDistance += velocity * Time.deltaTime;
    55.             currentDistance = currentDistance % pathLength;
    56.             dolly.m_PathPosition = curve.Evaluate(currentDistance);
    57.         }
    58.     }
    59. }
    60.  
     
  5. gdv_unity

    gdv_unity

    Joined:
    Sep 10, 2014
    Posts:
    4
    Hi Gregoryl,
    Great, your solution works fine. I can now move the camera with constant speed! :D
    Thanks a lot!
     
  6. quix22

    quix22

    Joined:
    Sep 6, 2018
    Posts:
    16
    Is there an updated version of this code for Unity version 2018.3.12f1? I'm looking for some way to have the camera move with constant speed on the dolly track. I'm just learning to include custom code in my projects but when I used the script above, it had problems with:

    SamplePath(path.m_Appearance.steps); // TODO: decouple numSteps from appearance setting
     
  7. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    This is very old, and is now outdated. Cinemachine now comes with a script called CinemachineDollyCart. You add it to a gameObject, connect it to a path, and it will move with constant speed along the path.

    You can have your vcam track the cart with a transposer or LockToTarget behaviour, or you can add a DoNothing vcam as a child of the cart.
     
  8. quix22

    quix22

    Joined:
    Sep 6, 2018
    Posts:
    16
    Thank you. I will try it out.
     
    Gregoryl likes this.
  9. quix22

    quix22

    Joined:
    Sep 6, 2018
    Posts:
    16
    Thanks Gregory, your suggestion worked like a charm. Previously, I had created the Cinemachine Dolly Camera with Track, and it didn't have the option for the constant speed. It was like being on a roller coaster; fast on turns and going down. This motion was disorienting for VR-type apps and recordings. Using your suggestion, I created the Dolly Track with Cart, I deleted the new Dolly Track (I already had a Dolly Track created), and kept just the Dolly Cart. The script for the Dolly Cart had the Speed variable that I adjusted to get the speed just right. I set the Path to the previously created Dolly Track and Added the Component for The Cinemachine Virtual Camera (DoNothing vcam). Viola! Does what I wanted it to do. Glad to have found this thread from a few years back how Unity has evolved the product to include this functionality out of the box.

    I'd like to enhance my project with a small drone flying directly in front of the DollyCart and was trying to figure out whether there's a way for an asset to be pathed to the DollyCart, but it seems like DollyCarts and DollyTracks are just for the vcams.
     
  10. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    The point of the dolly cart is to have something that can follow a path. It's just an ordinary object, not tied to vcams. You can attach anything to it. Also, you can have as many carts as you like on the same path.
     
  11. quix22

    quix22

    Joined:
    Sep 6, 2018
    Posts:
    16
    Very cool. Added this script (component) to the DollyCart and added my Drone GameObject as the Font Object. Working great. I'm going to have a lot of fun creating Dolly Tracks and Dolly Carts. Thanks again Gregory for the quick response.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class MovewithCamera : MonoBehaviour
    5. {
    6.  
    7. public GameObject frontObject;
    8. public float distance;
    9.  
    10. void LateUpdate()
    11. {
    12.     frontObject.transform.position =  this.gameObject.transform.position  + this.gameObject.transform.forward * distance;
    13.     frontObject.transform.rotation =    new Quaternion(0.0f, this.gameObject.transform.rotation.y, 0.0f, this.gameObject.transform.rotation.w);
    14.     }
    15. }
    16.  
     
    Gregoryl likes this.
  12. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    Why don't you just parent it in the hierarchy at the offset you like? That way you won't need the script.
     
  13. quix22

    quix22

    Joined:
    Sep 6, 2018
    Posts:
    16
    OMG. I disabled the script, threw the gameobject below the DollyCart...held my breath, and pressed Play. It worked! I'm just blown away by what Unity can do.

    upload_2019-5-14_12-59-55.png

    Thank you very much.
     
    Gregoryl likes this.
  14. mattis89

    mattis89

    Joined:
    Jan 10, 2017
    Posts:
    1,151
    How do I change speed to slower on the dolly track? (Not cart) @Gregoryl
     
  15. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    @mattis89 Track itself does not have a speed. What object are you talking about? Can you show the inspector?
     
  16. mattis89

    mattis89

    Joined:
    Jan 10, 2017
    Posts:
    1,151
    How fast the camera travels on the track.. how to change speed sir?
     
  17. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    There is no speed limit on the vcam if it's following a target. You can only control the damping. To do a speed limit you would have to put a vcam in a cart and implement your own movement - or have an intermediate invisible target that moves toward your real target at a fixed speed - and have the vcam track that instead
     
  18. mattis89

    mattis89

    Joined:
    Jan 10, 2017
    Posts:
    1,151
    Yes! I used a cart instead, works good... But the virtual camera noise profiles, I cant create new because create is greyed out, and I cant duplicate a preset nothing happends, and I when I mark a noise profile, I can click "gearwheel" or edit...? why have you guys locked it ?
     
  19. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    It's not locked for me. What version of CM are you using?

    upload_2019-11-7_16-23-50.png
     
  20. mattis89

    mattis89

    Joined:
    Jan 10, 2017
    Posts:
    1,151
    Latest from package manager... really weird... Also I build with no errors, still as soon as I run it, it crash (in build)
     
  21. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    "Latest from package manager" is not too helpful, as that will be different depending on what Unity version you have. Numbers are best.
     
  22. mattis89

    mattis89

    Joined:
    Jan 10, 2017
    Posts:
    1,151
    Cinemachine 2.2 with Unity 2019.2.9f1
     
  23. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    You should be using CM 2.3.4. Is it possible that you're using a very old CM from the asset store? 2.2 doesn't really make sense. Where exactly are your CM sources? Inside your project's Assets folder somewhere? If so, then there is a problem.
     
  24. mattis89

    mattis89

    Joined:
    Jan 10, 2017
    Posts:
    1,151
    I downloaded it from the package manager... Is there also 2,2 there? Maybe i didnt select latest verision..
     
  25. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    Try with the latest version
     
  26. mattis89

    mattis89

    Joined:
    Jan 10, 2017
    Posts:
    1,151
    Oh I will!
     
  27. mattis89

    mattis89

    Joined:
    Jan 10, 2017
    Posts:
    1,151
    Seems 234 actually was installed...
     
  28. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    I don't know what going on with your project, then. Does it work if you create a new project, install CM, create a vcam, and try to make a custom noise profile?
     
  29. mattis89

    mattis89

    Joined:
    Jan 10, 2017
    Posts:
    1,151
    Dont want to do that so.. created a new scene and copied over stuff from the other scene and now it works so I dont know lol.
     
  30. mattis89

    mattis89

    Joined:
    Jan 10, 2017
    Posts:
    1,151
    Hello @Gregoryl ! Everything is working great, Im just a bit confused when it comes to multiple cams... I have one camera now , wich I want to be the main camera wich is travelling on a trach.. its a dolly cart... And I have different locations wich I want to also be shown with a different cam.... How can I achieve this ? What do I need to animate ? I want to use timeline..
     
  31. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
  32. mattis89

    mattis89

    Joined:
    Jan 10, 2017
    Posts:
    1,151
    Yes Thanks! I cant find a blending option, and I dont mean blend 2 cameras ... I mean when a camera becomes active so it fades in the image and then out when the camera change.. So the image dont pop in and out.. smooooth fade in, like black first and you start to see the clear image like in 2 secs.
     
  33. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
  34. MoisesMM

    MoisesMM

    Joined:
    Apr 27, 2017
    Posts:
    1
    Hello,

    Recently I tested with cinemachine and it's really great, and more easier than I expected.

    However, I want to use cinemachine auto dolly for VR game, and the smooth path is really a headache for VR when stop the camera with smooth velocity.

    I see in this post that we can use Dolly Cart fot constant velocity, but it's not the same that auto dolly.

    ¿Some help to implement constant velocity with autoo dolly?

    Thank you very much, regards.
     
  35. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    Auto-dolly will position the camera on a path in relation to a target it's following. If the target moves, the camera moves. If the target stops, the camera stops.

    Constant velocity will move the camera on the path independently of what the follow target is doing.

    I don't understand how you want to combine these things. What would you like the camera to do when the target starts and stops?
     
  36. lucvw_1975

    lucvw_1975

    Joined:
    Dec 7, 2014
    Posts:
    20
    You saved my life man ! It seems I also was using the "old" way, have been searching for a week and then I found your post. So easy to setup and works without a flaw, thanks !
     
  37. Bowabadis

    Bowabadis

    Joined:
    Nov 22, 2020
    Posts:
    2
    When I assign the cart to my track, it moves at a constant speed which is good but it doesn't pivot or rotate with the track like the virtual camera does. What should I do to get it to move at a constant speed while being able to roll and rotate with the track?
     
  38. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    Indeed the cart does rotate to align itself to the track. Try putting something inside it (like a cube) so you can see what it does.
     
    Bowabadis likes this.
  39. Bowabadis

    Bowabadis

    Joined:
    Nov 22, 2020
    Posts:
    2
    Directly parenting the object in the hierarchy seemed to work. I was trying to parent the object through the script which was mainly my problem.
     
    Gregoryl likes this.