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

Bug Possible bug or just confusion with multiple Binding Modes

Discussion in 'Cinemachine' started by Catsploration, Jun 21, 2023.

  1. Catsploration

    Catsploration

    Joined:
    Mar 9, 2021
    Posts:
    68
    Hello, I think this is a bug, but I'm not sure. This is 2022.3.0, Cinemachine 3.0.0-pre.4

    Setup:
    • Create two Cinemachine Cameras (A and B) with the components in the attached image. Let them both have World Space binding modes for simplicity, or let one be World Space and the other Lock to Target with World Up as is the use case.
    • Set all dampening values to zero for simplicity.
    • Note: it doesn't matter if the De-occluder is enabled or not. This doesn't make sense to me given the following behavior.
    • On mouse press, swap camera priorities.
    Expected result: Camera priorities change, and the main camera is smoothly blended. Result: The expected result happens unless the camera is very close to or overlapping with scene geometry.

    However, if there is overlap, then main camera is moved directly behind the played at the maximum Vertical Axis value that is given in Cinemachine Orbital Follow component. This is not desired, since we want to seamlessly transition between A and B, leaving the main camera in its last location. A and B are used here because they have different binding modes, and I saw it recommended on the forums to use multiple Cinemachine cameras rather than to change the Binding Mode manually.

    Also, I tried upgrading to -pre.6 and -pre.7, but the Cinemachine package seemed to fail to compile. I had to downgrade back to pre.4. Any ideas?
     

    Attached Files:

  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,207
    Do try again to upgrade to pre-7. We can't support earlier versions of CM3. In what way did it fail to compile? Were there any console messages?

    Did you try Re-import all? Or if that fails, close Unity, delete your project's Library folder, then re-open the project.
     
  3. Catsploration

    Catsploration

    Joined:
    Mar 9, 2021
    Posts:
    68
    Here's a demo on imgur, it seems to ask for an age gate for some reason, which is weird: https://imgur.com/a/nLCBLoW

    I've tried uploading here, but mp4 and mkv are not allowed, and the 2mb video is converted to an 80mb gif with the program I tried, which is too large to upload. Please let me know if there's a better way to share videos.

    I have not tried reimporting all or deleting the library. I'll give that a try and post back here soon!
     
  4. Catsploration

    Catsploration

    Joined:
    Mar 9, 2021
    Posts:
    68
    Oops, that was embarrassing. It wasn't compiling due to the new `using Unity.Cinemachine` verse old `using Cinemachine`. I've now updated my scripts to match the API changes, deleted my Library folder, and let it reimport all.

    Edit: I better test a bit more before updating you! It looks like a lot of settings were adjusting when I upgraded, which led me to post a confusing comment here.
     

    Attached Files:

    Last edited: Jun 21, 2023
  5. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,207
    ok, I'll wait for more news from you
     
  6. Catsploration

    Catsploration

    Joined:
    Mar 9, 2021
    Posts:
    68
    This is how I'm blending between LockToTarget and WorldSpace binding modes,
    1. Let there be two CinemachineCameras: cameraLockToTarget and cameraWorldSpace
    2. Let the CinemachineBrain have a Default Blend time of 1s.
    3. Use cylindrical blend hints, do not inherit position.
    4. Let cameraLockToTarget have a higher priority unless a mouse button is pressed.
    5. When a mouse button is pressed,
      5.1a. If the camera is blending, use cameraWorldSpace.ForceCameraPosition with Camera.main.position. Set Blend Time to a small number such as 0.001f.
      5.1b. If the camera is not blending, use cameraWorldSpace.ForceCameraPosition with cameraLockToTarget.position. Set Blend Time to 0.
      5.2. Give cameraWorldSpace a higher priority value
    6. Now, when letting go of the mouse button, set brain.DefaultBlend.Time back to 1 and give priority back to cameraLockToTarget.
    7. The main camera blends back to cameraLockToTarget, which has stayed in a following location behind the player.
    Note 1: Default Blend time is set to zero here since, if the two cameras are already in the same location, then a blend time between the two will effectively feel like an unresponsive camera.

    Note 2: Default Blend time is set to 0.001 here since if 0 is used, there is a visual discontinuity. However, even with a blend time of 0.001, the camera remains unresponsive for I think just 1 frame, also motionless in world space, which is a noticeable hiccup/studder effect for the player's character if the player is in motion.

    Note 2's hiccup is the best I can do it seems, I've tried various things here, but I can't seem to figure out how to let the world space camera smoothly take on the main camera's blended transition position.

    Does this look right?

    ---

    Unrelated, here's something that might be worth mentioning, since I do not understand the behavior. Though, I've added in a simple solution already:

    With two CinemachineOrbitalFollow components both listening to the same ScrollY mouse action, the Live CinemachineOrbitalFollow responds with a larger scale than the other, though the other camera does also respond to the input. All values on the two Cinemachine cameras are the same, unless I've missed something.

    I've resolved this behavior by simply using
    Code (CSharp):
    1. orbitalFollowLockToTarget.RadialAxis.Value = orbitalFollowWorldSpace.RadialAxis.Value;
    where priority values are changed.
     
    Last edited: Jun 22, 2023
  7. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,207
    That looks kind of nutty. Why so complicated? Why not just do what you said initially (on mouse press, swap camera priorities)? What problem is being solved by this complicated logic?

    This is because when a vcam is inactive, it gets updated less often
     
  8. Catsploration

    Catsploration

    Joined:
    Mar 9, 2021
    Posts:
    68
    Well, nothing was solved by this. Rather a new problem was invented, haha.

    I cannot simply switch priorities here because at the time of the mouse press, Camera.main is in transition from A to B. I need to somehow: stop the camera in transition, let A inherit the in-transition position, and return priority from B to A.

    If,

    a) A is moved to the in-transition position and given priority with Default Blend Time = 0.001, then there is a 1 frame studder. I'm not sure why there's a 1 frame studder here (the camera is unresponsive to input and motionless in world space), I guess this is just how Blends work, or maybe it's related to needing an orientation frame after calling ForceCameraPosition? However, without a blend, as is in b),
    b) A is moved to the in-transition position and given priority with Default Blend Time = 0, then there is a visual discontinuity, A is teleported near the Camera.main's position, but it's not exact.

    Also, for the other question, that makes sense, thanks!
     
    Last edited: Jun 22, 2023
  9. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,207
    I'm not seeing the problem. Cinemachine can handle nested blends gracefully. (A->B)->A etc should work just fine. No special logic necessary. Why won't this work for you?
     
  10. Catsploration

    Catsploration

    Joined:
    Mar 9, 2021
    Posts:
    68
    You're absolutely right, I just tried to reproduced the 1 frame studder again and I can no longer do so. All I have to write for (A -> B) -> A is,

    Code (CSharp):
    1. cameraWorldSpace.ForceCameraPosition(Camera.main.transform.position, Camera.main.transform.rotation);
    2. brain.DefaultBlend.Time = 0;
    Where the priority is changed.

    Thank you for getting me on the right track! I was quite confused, haha.

    Working demo: https://imgur.com/a/VNVs22a
     
  11. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,207
    You don't even need to do that much.
    • ForceCameraPosition is unnecessary. Enable the "InheritPosition" blend hint in the incoming vcam and it's automatic.
    • Why modify brain.DefaultBlendTime? You can set custom blend rules for specific cameras in the Custom Blends section of the brain. So set the default blend to something reasonable, and leave it constant.
    • The only thing you need to do is to swap priorities, or activate one and deactivate the other. Your choice.
     
  12. Catsploration

    Catsploration

    Joined:
    Mar 9, 2021
    Posts:
    68
    If I remove my one line where I force the position, and instead enable InheritPosition, then the camera warps to B when A is given priority during the (A -> B) transition.

    (Edited note: A is World Space on mouse press and B is a fixed Lock to Target mode centered behind the player.)

    Here's a demo with these changes: https://imgur.com/a/sUSDB0G

    I'm adjusting DefaultBlendTime because I don't know how Custom Blends work yet. I'll give these a try, thank you!
     
    Last edited: Jun 23, 2023
  13. Catsploration

    Catsploration

    Joined:
    Mar 9, 2021
    Posts:
    68
    Okay, I'm actually back to the initial question,

    If we interrupt an (A -> B) transition by: giving priority back to A and calling ForceCameraPosition to Camera.main, then, if the camera is currently near/inside geometry, then the main camera is moved directly behind the played at the maximum Vertical Axis value that is given in Cinemachine Orbital Follow component. Like before, it does not matter if the De-occluder is enabled or not.

    Demo: https://imgur.com/a/LkKXXSM

    I don't know if this behavior will be the same when InheritPosition is used instead of ForceCameraPosition, because in that case, the camera is instantly warped to B on interruption.

    Edit:

    I tried using Custom Blends in the brain component to make sure brain.DefaultBlendTime wasn't a source of error. The behavior remains the same either way.
     
    Last edited: Jun 22, 2023
  14. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,207
    Would you like to share the project with me? I can't tell what's going on from the video.
     
  15. Catsploration

    Catsploration

    Joined:
    Mar 9, 2021
    Posts:
    68
    Well, I have a lot of junk in this project. I've just noticed the Cinemachine Samples project, which I think I should have started this conversation by using! I've included all the steps here so that you can reproduce them, or just use the attached .unitypackage that I have included.

    1) Make a new project, URP 2022.3.3f1.
    2) Import Input System, Cinemachine (git URL: com.unity.cinemachine@3.0.0-pre.7), and Cinemachine Samples.
    3) Duplicate the sample scene FreeLook Deoccluder and rename it "FreeLook and LockToTarget"

    For scene "FreeLook and LockToTarget,"

    4) Set range for the existing Orbital Follow Vertical Axis to -45 and change Orbit Style to Sphere.
    5) Make sure the Input Axis Controller is using actions from CinemachineDefaultInputAcitons.
    6) Create CinemachineCameraPriorityToggler.cs, attach the component to the main camera, assign references, and add a Cinemachine Input Axis Controller to the Main Camera.

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3. using Unity.Cinemachine;
    4.  
    5.  
    6. public class CinemachineCameraPriorityToggler : MonoBehaviour, IInputAxisOwner
    7. {
    8.     [SerializeField] CinemachineCamera cameraFreeLook;
    9.     [SerializeField] CinemachineCamera cameraLockToTarget;
    10.  
    11.     public InputAxis Fire = InputAxis.DefaultMomentary;
    12.  
    13.     void IInputAxisOwner.GetInputAxes(List<IInputAxisOwner.AxisDescriptor> axes)
    14.     {
    15.         axes.Add(new() { DrivenAxis = () => ref Fire, Name = "Fire" });
    16.     }
    17.  
    18.     void Start()
    19.     {
    20.         Cursor.lockState = CursorLockMode.Locked;
    21.     }
    22.  
    23.     void Update()
    24.     {
    25.         if (Fire.Value > .5f)
    26.         {
    27.             if (cameraFreeLook.Priority.Value != 2)
    28.             {
    29.                 cameraLockToTarget.Priority.Value = 1;
    30.                 cameraFreeLook.Priority.Value = 2;
    31.             }
    32.         }
    33.         else
    34.         {
    35.             if (cameraLockToTarget.Priority.Value != 2)
    36.             {
    37.                 cameraFreeLook.Priority.Value = 1;
    38.                 cameraLockToTarget.Priority.Value = 2;
    39.             }
    40.         }
    41.     }
    42. }
    Now that that's set up,

    7) Duplicate FreeLook Camera and name it LockToTarget Camera.
    8) Set the binding mode to Lock to Target With World Up.
    9) Enable recentering for both horizontal and vertical axis on the LockToTarget Camera.
    10) Set Blend Hint Cylindrical Position for both cameras, and Inherit Position for the FreeLook Camera.
    11) Add two Custom Blends in the brain. Let the transition from FreeLook to LockToTarget be Linear at 1s. For the reverse transition, use Cut.

    Now, to test, just rotate the camera, then click the mouse button before it has fully recentered.

    Expected behavior: the main camera stops in transition instead of warping to LockToTarget Camera's position.
    Actual behavior: the main camera warps to LockToTarget Camera's position.

    Demo: https://imgur.com/a/Hv5GbLN
     

    Attached Files:

  16. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,207
    Thanks for the project! I was able to repro. The problem is that you have recentering enabled in the OrbitalFollow, so it gets activated to a recentered state. If you disable recentering, then it works perfectly.

    I think this is a bug. When InheritPosition in enabled, it shouldn't activate to a recentered state. We will fix this.
     
    Catsploration likes this.
  17. Catsploration

    Catsploration

    Joined:
    Mar 9, 2021
    Posts:
    68
    Happy to help! Other tasks have caught up with me, but I had a moment to test again today. Disabling recentering does not seem to work in my testing.

    I've updated the demo scene to better highlight the desired behavior/gameplay, and also for other users, should they find their way here.

    In the scene FreeLook and LockToTarget,

    1) Value and Center for the Vertical Axis was set to 40, for both cameras. Player speed was increased to 5.
    2) Disable Look Orbit X and Y in the Lock To Target Camera.
    3) Rename the scene to "Lock To Target and World Space Blending." Rename "FreeLook Camera" to "World Space Camera"
    4) Add player.Strafe = true; in the priority toggler script, for when the mouse is held down. player.Strafe = false; when released.
    5) Update the custom blend in the brain and serialized references in the priority toggler.
    6) Make sure the World Space camera's Rotational Composer and Orbital Follow do not have dampening.
    7) For SimplePlayerController.cs, let InputForward be Player.

    The player can now walk around more comfortably, though, there's still something weird going on with the Lock To Target's camera rotation that is unrelated to the blending question. I think SimplePlayerController.cs would need to be modified for this to fully work, since the player should be able to turn in place when Left or Right is held down.

    8) Center On Activate is checked for both cameras. We are toggling priority, so I think this is okay.
    9) The Recentering checkboxes for all three Axis are disabled, for both cameras.

    Demo: https://imgur.com/a/JD8CdPn

    The updated scene file is attached.
     

    Attached Files:

  18. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,207
    Thanks for that. I don't think there are any action items for us there, it seems to work well.
    FYI we've fixed the recentering bug, the fix will be available in the next pre-release (3.0.0-pre.8)