Search Unity

How do I teleport a Cinemachine Freelook Camera without it lerping

Discussion in 'Cinemachine' started by paleonluna, Dec 6, 2017.

  1. paleonluna

    paleonluna

    Joined:
    Jan 31, 2014
    Posts:
    12
    I have a section of my game where I teleport the character across the map without warning.

    It uses a freelook camera and cinemachine brain. On teleport, I move the player to a new position and try to move the camera to the right position, but it insists on overriding my set transform.position call and lerps over to where it should be very quickly, effectively turning what I want to be a hard cut into an unwanted instant lerp. Do you have any idea how I can fix this? I dont think swapping between two freelook cameras is a good idea, and it seems like it is always going to try to lerp if it is displaced.

    Thanks,

    Pablo
     
    DChap likes this.
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    3,375
    Disabling then re-enabling the vcam after teleporting the target will snap it to the new position.
     
    wlwlz likes this.
  3. paleonluna

    paleonluna

    Joined:
    Jan 31, 2014
    Posts:
    12
    Alright, I tried that in an earlier version and it did not work, it seemed to cache some positions. But I will update and try again.

    Thank you.
     
  4. paleonluna

    paleonluna

    Joined:
    Jan 31, 2014
    Posts:
    12
    Unfortunately, what happens is that when you re-enable the vcam, it does at first snap to the position but then immediately after interpolates from the old position to the where it should be - in my case flying through a bunch of a level objects along the way.

    It seems that if I could empty the cache of where it thinks it was last that would do the trick. Any ideas?

    Thanks,

    Pablo
     
  5. JakubSmaga

    JakubSmaga

    Joined:
    Aug 5, 2015
    Posts:
    417
    What about changing Default Blend in the CM brain to Cut?
     
  6. paleonluna

    paleonluna

    Joined:
    Jan 31, 2014
    Posts:
    12
    Re-enabling the brain
    I am not switching cameras - I am turning a FreeLook and a Brain on and off. Switching to Cut has no effect. Thanks for the suggestion though.
     
    wlwlz likes this.
  7. JakubSmaga

    JakubSmaga

    Joined:
    Aug 5, 2015
    Posts:
    417
    I've just tried re-enabling my FreeLook, Brain and there is no lerping, just cut.

    Which Cinemachine version are you using?

    (Also could you file a repo project?)
     
  8. paleonluna

    paleonluna

    Joined:
    Jan 31, 2014
    Posts:
    12
    Version 2.1.10

    Did you translate your target as well as your freelook by the same amount in between your enable/disable?

    (Also could you file a repo project?) what do you mean by this? I unfortunately cannot share this project.
     
  9. JakubSmaga

    JakubSmaga

    Joined:
    Aug 5, 2015
    Posts:
    417
    Yeah I've changed my transform position after disabling CM Brain and enabling it again.
    Repo project is just an empty project which shows the bug.
     
  10. paleonluna

    paleonluna

    Joined:
    Jan 31, 2014
    Posts:
    12
    Ok I am at work for the day but when I get home I will try to file a repo project.
     
  11. paleonluna

    paleonluna

    Joined:
    Jan 31, 2014
    Posts:
    12
    Are there any other notable settings that you are using on your camera to have a clean cut across world space?
     
  12. shedworksdigital

    shedworksdigital

    Joined:
    Nov 7, 2016
    Posts:
    40
    I've been trying to get this working today and have had some success. Rather than disabling/enabling the vcam component, you need to set its GameObject Inactive/Active. It's not longer lerping all the way across the scene, but there is a little judder when I set the new position. It also goes totally wild if I try and do this in the middle of a camera blend so it's not really a proper solution.
     
  13. paleonluna

    paleonluna

    Joined:
    Jan 31, 2014
    Posts:
    12
    ah thanks. Yeah, I realized that my prob may be associated with the fact that I am on 2017 2.0b8 but once I upgrade I will check again.
     
  14. spakment

    spakment

    Joined:
    Dec 19, 2017
    Posts:
    28
  15. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    2,158
    That one does teleport following of the camera, but doesn't warp the aim component, e.g. Group Composer.

    Does anyone know how to adjust the Group Composer, so it would look towards the look at transform after teleportation? Calling OnTargetObjectWarped manually on the Group Composer doesn't seem to work.
     
  16. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    3,375
    OnTargetObjectWarped will only correct the position. It is assumed that the aim will remain the same. Are you not warping all the group members? If you are, then the aim staying the same should work.
     
  17. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    2,158
    Yeah, this is a problem that aim stays the same instead of looking to the look at object.
    I guess altering rotation of the vcam directly should work. Need to try that.
     
  18. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    3,375
    Are you not warping all the group members?
     
  19. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    2,158
    Nope, just the virtual camera.

    Setting rotation directly didn't worked either.
     
  20. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    2,158
    Okay, so I've figured out this works perfectly (resets both position and rotation correctly for me):
    Code (CSharp):
    1.         private void TeleportCamera() {
    2.             _virtualCamera.Follow = null;
    3.             _virtualCamera.LookAt = null;
    4.        
    5.             StartCoroutine(UpdateCameraFrameLater());
    6.         }
    7.  
    8.         private IEnumerator UpdateCameraFrameLater() {
    9.             yield return null;
    10.        
    11.             _virtualCamera.Follow = *yourTargetToFollow*;
    12.             _virtualCamera.LookAt = *yourLookAtTarget*;
    13.         }
    Shame it requires a small coroutine alloc, but its better than non-working teleportation.
     
  21. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    3,375
    Glad you got it sorted out. Just for clarity, if you teleport the camera position while asking the camera to look at something, you shouldn't be surprised if the camera keeps looking at that something from its new position.
     
  22. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    2,158
    Well, that something's position is the thing that has changed.
    And the camera is being teleported to that position no problems via OnTargetObjectWarped.

    Its the rotation that is kept the same which cannot be "warped" because that method doesn't exist.

    It would be nice to have some kind of API to force update position and rotation in a "cut" manner instead of relying upon workarounds that might stop working in a future versions.


    Because to be honest - OnTargetObjectWarped is terrible from the user / other programmer's perspective.
    Calculating delta direction / distance vector just to snap camera to its new position, really?

    Something is happening upon = null / = newTarget. That something could be put into that sweet "teleport" or "snap" method.

    If there's a certain technical limitation why it doesn't exist, or why its done that way, it would be nice to know it.
    Probably worth putting into docs.

    Just my 2 cents.
     
    Last edited: Sep 25, 2019
  23. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    3,375
    Maybe I'm not understanding your setup.

    Here is what I understand:
    1. vcam is following targetA, and looking at groupB.
    2. targetA gets warped, and you call vcam.OnTargetObjectWarped() to inform the vcam that the thing got warped and that it should not do a damped follow, as it would if targetA just moved very quickly
    3. groupB (and all the objects it contains) remains where it was before
    4. Result: vcam position warps correctly, but it continues to look at groupB, you can't give it a new rotation
    Is that accurate?
     
  24. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    2,158
    1. vcam is following targetA, looking at targetA;
    2. targetA gets warped and I'm calling vcam.OnTargetObjectWarped();
    3. There's no group B.
    4. As a result: position warps correctly, but the rotation is kept the same, leading to the slow vcam rotation (due to damping) from the previous rotation towards new position of the targetA.

    Edit: I'll post screenshot of the setup tomorrow, if that would be helpful.
     
    Last edited: Sep 25, 2019
  25. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    3,375
    Ah, ok. I was misled by this:
    I'm still a little unclear on what exactly is going on, because of your point 4. OnTargetObjectWarped() will preserve the vcam-to-target spatial relationship, so I don't really understand why any rotation is needed.

    Can you show me a picture of your vcam inspector? I should have asked you to do that in the first place.

    Also: what parameter are you passing to OnTargetObjectWarped()?
     
  26. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    3,375
  27. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    2,158
    Already tried that, it didn't catch up if done in a single frame. The only workaround that worked out for me is the one posted above.

    Here's a vcam setup:
    upload_2019-9-26_11-20-18.png

    I'm pretty sure extra damping / rotation is caused by Tracked Object Offset property.
     
  28. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    3,375
    ok, I understand now. When you teleport the target you also rotate it, and your binding mode is LockToTarget, so the vcam will have to change position/orientation because the offset is in target-local space. OnTargetObjectWarped() won't do the job for you because, as you pointed out, it only handles a change of position, not a change of rotation.

    Yes, disabling the vcam and re-enabling the same frame won't work, because the vcam's OnEnable() method won't get called until the next frame. Sorry, I didn't think of that in my previous post. Try instead to reset the vcam by setting vcam.PreviousStateIsValid = false. That should make the vcam snap to the new spot.
     
    xVergilx likes this.
  29. awiebe

    awiebe

    Joined:
    Oct 16, 2018
    Posts:
    3
    I've tried these steps and it doesn't seem to have correctly updated the rotation of the virtual camera. I am using the prebuilt rig which comes with the 3d platformer kit.

    I have augmented it with two scripts:
    • MainVCam: A singleton that allows me to broadcast information to the actual main virtual camera.
    • PortalTrigger: Causes my camera to be repositioned and rotated... or at lest it should

    Code (CSharp):
    1. public class MainVCam : MonoBehaviour
    2. {
    3.     public static MainVCam singleton;
    4.     public Cinemachine.CinemachineFreeLook[] cams;
    5.  
    6.     public Vector3 position { get; internal set; }
    7.     public Quaternion rotation { get; internal set; }
    8.  
    9.     // Start is called before the first frame update
    10.     void Start()
    11.     {
    12.         singleton = this;
    13.     }
    14.  
    15.     public void Invalidate()
    16.     {
    17.         foreach (Cinemachine.CinemachineFreeLook c in cams)
    18.         {
    19.             c.gameObject.SetActive(false);
    20.             c.PreviousStateIsValid = false;
    21.             c.transform.position = position;
    22.             c.transform.rotation = rotation;
    23.             c.gameObject.SetActive(true);
    24.         }
    25.         Debug.Break();
    26.  
    27.  
    28.     }
    29. }
    Code (CSharp):
    1. public class PortalTrigger : MonoBehaviour
    2. {
    3.     public Camera camera;
    4.  
    5.     void OnTriggerEnter(Collider other)
    6.     {
    7.  
    8.         if (other.tag == "Player")
    9.         {
    10.             //MainVCam.singleton.gameObject.SetActive(false); //doesn't seem to work
    11.             Transform playert = other.transform;
    12.             Transform l_cam = Camera.main.transform;
    13.             Transform oldParent = playert.parent;
    14.  
    15.             //Move the player in relation to the camera rendering the portal so the transition is seamless
    16.             //Rotate the player so they are facing towards the same direction as the camera rendering the portal  
    17.             //so they are correctly oriented camera relative when they arrive.
    18.             Vector3 relpos = l_cam.InverseTransformPoint(playert.position);
    19.             playert.position = camera.transform.TransformPoint(relpos);
    20.             playert.rotation = Quaternion.LookRotation(camera.transform.forward, Vector3.up);
    21.  
    22.             //Update vcams
    23.             MainVCam.singleton.position = camera.transform.position;
    24.             //Orient the camera to face the same way as the camera that rendered the portal
    25.             //This is the part that doesn't work
    26.             MainVCam.singleton.rotation = camera.transform.rotation;
    27.             MainVCam.singleton.Invalidate();
    28.             //MainVCam.singleton.gameObject.SetActive(true);
    29.         }
    30.     }
    31. }
    Conversely if I just turn off the virtual cameras and reposition the main camera directly it pops right into the correct position. Then as soon as I turn the virtual cameras back on it is at the correct position, but the orientation screws up, as if it did not invalidate the orientation.
     
    Last edited: Jan 3, 2020
  30. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    3,375
    @awiebe You are using FreeLook vcams, which have the added complexity of axis values, which don't get repositioned automatically by default. My guess is that the axis values are not set appropriately after the position warp. Try setting them to 0 and placing the freeLook appropriately so that this value makes sense. I don't know how you've set up your FreeLook so I can't give any more details.

    Maybe also this might help: https://forum.unity.com/threads/setting-direction-for-freelook-camera.802497/#post-5343048
     
  31. awiebe

    awiebe

    Joined:
    Oct 16, 2018
    Posts:
    3
    It is using the classic input system's mouse movement, which returns the delta of the mouse.(The 3DGamekit Lite calls this axis CameraX and CameraY respectively. If the mouse is stationary there is no input, therefore passing through the portal with the mouse neutral the axis are zeroed.

    As I understand it this means that the inputs to cinemachine are zero.

    The camera also appears to be facing the exact direction and is in the same position relative to the lookat as before I teleported the lookat position.

    Symptomatically it is appears more like the new position and orientation were not considered when resuming the camera. Since the main camera simply copies the transform of the destination camera, and then the player is transformed relative to the main camera to match the same relative position, it seems to me that when the freelook cam is re-enabled cinemachine should evaluate the shot, see that it is in a valid position and get on with its day, that is unless manually relocating this camera in some way breaks the virtual camera's state.

    It is as if when the target is teleported OnTargetObjectWarped happens, and the rig just looks at where it was and where the target is, and moves the brain according to its last known relative position and orientation. However for this use case it should have also evaluated that the Brain has also been warped and indeed transformed.

    If that is a weird edge case behaviour you don't want to evaluate when an object is warped that's fine, but then setting the last frame invalid should also make sure the camera checks if it is in a valid relative position, and not try to snap as if only the target warped, or there needs to be a seperate call to tell the camera that it was also moved.
     
  32. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    3,375
    You must distinguish between axis input and axis value. The axis keeps a value, which defines the FreeLook's relationship to the target. Mouse input will change that value while there is input, but when the input stops, the value remains fixed. That's why the FreeLook's relationship to the target remains unchanged after the warp. It is correct behaviour, because the FreeLook's job is to position and rotate the camera as a function of the target's location and the axis values, and the axis values are controlled by the user, not by the FreeLook.

    If you want to reset the axis values when teleporting then you must do so manually, as I suggested in my previous post. Setting the position and rotation directly will not be effective, as the FreeLook will overwrite them in response to axis values and target position.

    upload_2020-1-10_8-32-29.png

    You might then ask the question: what are the correct axis values to set? The answer to that depends on your FreeLook settings. If you would show me the inspector and describe to me the desired FreeLook-to-target relationship after the teleport, I might be able to help you with that.
     
unityunity