Search Unity

Free look camera with world space binding and overriden world up

Discussion in 'Cinemachine' started by Molioo, Oct 3, 2018.

  1. Molioo

    Molioo

    Joined:
    Mar 12, 2016
    Posts:
    7
    Hello,
    At start I have to say that i am pretty amateur with cinemachine.

    In my game I am using Free look camera with world space binding and it works great when player is walking on the normal ground like floor.
    When player is moving forward, he's moving in camera.forward direction, if he's moving right, he goes in camera.right direction etc.
    I also have this situations where player can walk on the walls and his "up" is parallel to wall normal.
    In this case world space binding isnt working as camera orbits are placed with world up and not player up. It is so even if I have correct (same as player) World Up Override in Cinemachine Brain.

    Camera is working good (it has player up) on walls when it's set to Simple Follow With World Up and Lock To Target With World Up but with these setups, my player movement isn't working good.

    Camera Screen X i set to 0.4 and Screen Y is set to 0.65. My player movement is depending on camera rotation.

    In world space binding when I run forward, camera position relative to player isnt changing, but in simple follow with world up its changing and goes to left. That causes that camera rotation goes to right and player is slowly going forward-right. Also going right or left only doesnt work good.
    In Lock To Target binding when I run forward with camera directed to forward its ok but when I move my mouse to right or left and camera isnt directed in player forward, my player starts to run in circles.

    Is there something I can do to have my free look camera behave like it's set to world space binding but also tolerating player up being different than world up?

    It's pretty hard for me to explain it, I hope You can somehow understand this.
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    These kinds of things are very difficult to describe. Posting a little video is often helpful, and images of the inspectors. I think the whole thing is summed up in your last sentence, right?

    Setting the world up override in the brain would be my first instinct, but you say it's not working the way you need. Have you tried LockToTarget binding mode? That might give you the right FreeLook orbits, but you'll have to do a little work to get the player's forward to always match camera forward. Leaving aside for now the problem of player movement, what happens when you try that?

    What version of CM are you using?
     
  3. Molioo

    Molioo

    Joined:
    Mar 12, 2016
    Posts:
    7
    I am using CM 2.2.7.

    When binding is set to WorldSpace it looks like this (even with world up override is set):
    https://imgur.com/cFcr0VF
    Setting LockToTarget binding mode creates correct FreeLook orbits,same as LockToTargetWithWorldUp( when world up override is set).

    When it's set so, it looks like this:
    https://imgur.com/2qKKHgH
    My movement works best with WorldSpace and I was hoping that maybe there is some way to use it in also in case when player is i.e. on wall.
     
  4. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    If you want the camera orbits to be right, you can't use world space. You have to use one of the other modes. I recommend LockToTarget, because it's simpler. So now it's just a question of getting the movement right.

    The difficulty will be the X axis. Maybe you can try this:

    Leave the Y axis on the FreeLook alone, but disconnect the mouse X from the X axis. Put nothing as the axis name. Then, add a little script to the player to turn it left/right (player-local) in response to mouse X. Camera will automatically follow. This should behave the same as world binding did.
     
  5. OhiraKyou

    OhiraKyou

    Joined:
    Mar 27, 2012
    Posts:
    259
    I'm in this boat as well. Setting the world up override should actually override the world up, resulting in the camera working as if the world up was what was specified rather than Vector3.up. A forward and right vector can be obtained from the same reference transform to facilitate this. Basically, I don't just want a "world up" override. I want a "world space" override—a transform whose up/forward/right vectors are simply used instead of Vector3.up/forward/right in all Cinemachine code. Anywhere Vector3.up/forward/right is used, a property that returns the most available value should be used instead. Example:
    Code (CSharp):
    1.  
    2. [SerializeField]
    3. private Transform _worldSpaceOverride;
    4. public Transform WorldSpaceOverride {
    5.    get { return _worldSpaceOverride; }
    6.    set { _worldSpaceOverride = value; }
    7. }
    8.  
    9. public Vector3 CameraUp {
    10.    get { WorldSpaceOverride ? WorldSpaceOverride.up : Vector3.up; }
    11. }
    12.  
    13. public Vector3 CameraForward {
    14.    get { WorldSpaceOverride ? WorldSpaceOverride.forward : Vector3.forward; }
    15. }
    16.  
    17. public Vector3 CameraRight {
    18.    get { WorldSpaceOverride ? WorldSpaceOverride.right : Vector3.right; }
    19. }
    20.  
    For flexibility and compatibility with existing code, you can even use separate transforms for the up, forward, and right overrides. Although, one transform may make more sense, as intermediate vectors may need transformed and rotations multiplied as well.

    For example, if an entire game were made with a world rotated, it should be possible to integrate a Cinemachine FreeLook without changing camera code by simply overriding the world reference transform(s) to whatever you want the game's up/forward/right vectors to be through a transform reference or three. If an entire game and world space reference transform(s) were rotated the same amount, the result should be indistinguishable from an unrotated world from the player's perspective.

    To demonstrate, the gravity vector of my character is dynamic. It's possible, for example, to walk on or orbit around the surface of a rotating planetoidal sphere. The camera input should remain consistent during this, as if walking on the surface of a planet.

    Example orbit with an existing FreeLook (without world space overriding):
     
    Last edited: Nov 27, 2018
  6. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    @OhiraKyou This is exactly what we have in CinemachineBrain:

    upload_2018-11-29_11-5-30.png

    Put your player in that field. Does it not work for you?
     
    Last edited: Nov 29, 2018
  7. OhiraKyou

    OhiraKyou

    Joined:
    Mar 27, 2012
    Posts:
    259
    It is set to the player's transform and doesn't work. I should mention that I'm currently on Cinemachine 2.1.10 due to the dropped support in Unity 2017. But, given that I found 2 threads (this one included), almost a year apart, while looking for a solution, and that this thread was just a month and a half old, I suspected that it hadn't yet been fixed.

    This shows the difference between trying to rotate the camera horizontally while nearly on top of a sphere and while on the side:
     
  8. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    It works for me in CM 2.2.7. I have a FreeLook with SimpleFollow binding mode, following the player. World Up Override is set to the player. Everything behaves properly when I rotate, regardless of player orientation. What is your setup?

    By the way, CM 2.2.7 will work with 2017. You can download it using 2018 then copy it from the cache to your project.
     
  9. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    Here is a sample gif showing it in action (sorry for the low color res)
     

    Attached Files:

  10. OhiraKyou

    OhiraKyou

    Joined:
    Mar 27, 2012
    Posts:
    259
    I tried it in Unity 2018.2.17f1, with Cinemachine 2.2.7, and it still doesn't work. I'm using a FreeLook. The orbits binding mode is world space, and it is not unreasonable to expect a "world space" binding to respect on override that exists specifically to redefine "world space". Indeed, any binding mode that does not respect the world up override is bugged (or, at the very least, not fully integrated).

    Consider the following: there could be a "World Space With World Up" option. But, that sounds redundant because it is. Ideally, all binding modes should respond to world space overriding by default. But, I'd take a redundant binding mode over a malfunctioning binding mode. Alternatively, it could be a checkbox, separate from the binding mode selection.
     
    Last edited: Dec 1, 2018
  11. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    Well, the world up override does for me what you describe you need. See my gif above. What are you doing that's different?
     
  12. OhiraKyou

    OhiraKyou

    Joined:
    Mar 27, 2012
    Posts:
    259
    It's the binding mode; SimpleFollowWithWorldUp (used in your example) works, but WorldSpace does not. And, as the purpose of the world space override is to override the definition of world space, it should.
     
  13. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    It's true, WorldSpace really is world space. All the other binding modes work with the override, however.

    Suppose WorldSpace binding mode really did what you propose, i.e. use the override in the brain. Not a terrible idea at all. However, if you then set the override to be Player, then you would have a situation that is equivalent to LockToTarget binding mode, which already works with arbitrary orientation. So why not use that?
     
  14. OhiraKyou

    OhiraKyou

    Joined:
    Mar 27, 2012
    Posts:
    259
    Solid point there. Turns out, this is actually somewhat complicated. But, I have a possible solution for an additional binding mode that would achieve the functionality I'm looking for.

    First, the description. My ideal camera binding would act like WorldSpace, maintaining its relative position to the player without rotating as they strafe. But, it would also maintain orientation to gravity (the player's up vector).

    The world up override's up vector represents the normal of a virtual plane. So, the difficulty comes in knowing where the forward vector should be in order to position the camera in the same relative space while ignoring the up override's yaw (so that the player can strafe without the camera sticking behind them).

    To do this, perhaps an inverse delta yaw could be calculated from the override's current to previous yaw. Then, the override's previous plane-relative forward vector could be reconstructed by rotating its current forward vector by this delta yaw. In theory, you should then have an up and forward vector that are functionally identical to the world space up and forward vector, with the significant difference being that it would work as expected while walking on the surface of a sphere or under any other condition that would rotate the world up override.

    And, of course, you could get the right vector from the cross product of the forward and up vector, enabling the reconstruction of the camera's relative position as the sum of the camera's previous relative coordinates multiplied by each vector. So, that would be something like previous.x * right + previous.y * up + previous.z * forward. There may be more efficient and elegant methods of calculating the position, but that's the first thing that came to mind.

    Ultimately, the result should be that the player can walk on the surface of a spherical planet with WorldSpace style camera behavior.

    For reference, this is WorldSpace vs LockToTarget behavior in one GIF:
     
    Last edited: Dec 3, 2018
    andreiagmu likes this.
  15. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    You could test out that idea by adding an invisible child object to your player, with a script on it to manipulate its orientation as you describe. Then use that child as a target, with LockToTarget binding mode.
     
  16. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    175
    I see you're using Kinematic Character Controller, yes? :) I'm using it too in my game, and I'm having the same camera issues as you, when my character moves at the spherical planet.
    Have you somehow managed to make the camera behave the way you want?

    I'm almost giving up using Cinemachine because of those issues...
     
    Last edited: Feb 28, 2019
  17. OhiraKyou

    OhiraKyou

    Joined:
    Mar 27, 2012
    Posts:
    259
    Yep, I swapped out my dynamic controller for Kinematic Character Controller a while back. I haven't implemented a solution to spherical movement myself yet; it's low on the priority list until I have a proper level that requires it.
     
    andreiagmu likes this.
  18. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    175
    I managed to implement a solution for spherical movement! (and I guess movement in any angle)
    Maybe it'll make the camera behave the way you want.

    That rapid spinning behaviour that happens in LockToTarget, is because the camera always tries to get behind the character. And as the character's forward vector is rotated when we move to some direction, the camera still tries to get behind the character before doing anything else.

    To fix that, I created a separate object (let's call it CameraFollowTarget), that isn't a child of my character, but always has the same transform.position of the character.
    I move CameraFollowTarget's transform.position together with my character's transform.position. But I don't pass the character's rotation to CameraFollowTarget.

    My CinemachineBrain has my character's transform assigned as the World Up Override.
    My FreeLook vcam has Follow assigned to CameraFollowTarget's transform, LookAt assigned to my original lookAt target (the character itself, or some child of the character, for example positioned in its head), and Binding Mode assigned to "Lock to Target With World Up".

    Then (if I'm not forgetting something), the camera should behave like in the WorldSpace binding mode, but with the World Up Override working nicely!

    Here's a GIF of my results:
     
    Last edited: Mar 15, 2019
  19. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    175
    Just a warning: Using my method, I guess you can't use the vcam's Heading Definition as "Target Forward", because the CameraFollowTarget object won't rotate. But I think you can use "Position Delta" or "Velocity" definitions just fine.

    It would be nice if there was a way to use the Target Forward heading definition, but with an arbitrary target instead of using the vcam's assigned transform in Follow.
     
  20. Malaussene

    Malaussene

    Joined:
    Feb 14, 2017
    Posts:
    17
    Was anyone able to work this out? I'm trying to achieve the same but with no luck so far.
    I have free look camera set to World Space binding mode, a camera relative movement controller and this platform with inverted gravity. All I want to do is to roll the camera so that its rotation sticks to the character up (somewhat like Lock To Target binding mode does). Any hint? Thank you!
     
  21. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    175
    I think the World Space binding mode won't work in your case. To make that camera behaviour, you need to use Lock to Target (With World Up, I guess) binding mode, and set your character/controller's transform as the World Up Override in your CinemachineBrain. Have you tried that?
     
  22. lordzeon

    lordzeon

    Joined:
    Jun 1, 2018
    Posts:
    44
    I know this is old, but you just saved me lot of time with this solution, thanks! i had the camera follow (mounts in my case, but they had the World Up as i wanted, so the result was unexpected, maybe world Up Vectors are added.
     
    andreiagmu likes this.
  23. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    175
  24. lordzeon

    lordzeon

    Joined:
    Jun 1, 2018
    Posts:
    44
  25. NilsRamstoeck

    NilsRamstoeck

    Joined:
    Aug 13, 2020
    Posts:
    1
    I had a similar problem as the one described here and managed to resolve it with Binding Mode LockToTarget and then setting Heading to World Forward
     
  26. KennPrins

    KennPrins

    Joined:
    Jul 18, 2021
    Posts:
    17
    Hi @andreiagmu, can I know how you handled the rotation towards the direction that the camera is facing? I tried what you have mentioned in this post and the player keeps spinning on the Y axis without stopping when I move the camera.
     
  27. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    175
    Hi, for now, I'm not using that camera system anymore, so I can't help you with that.
    Have you tried all solutions from this thread? (check out the posts made after my original post)

    Also, you can check out this other thread (that I also I linked in a post above), for more possible solutions:
    https://forum.unity.com/threads/how...hird-person-shooter-game.739379/#post-4936277

    Before anything else, you may want to check the Third Person Camera tutorial linked at the end of that other thread.
     
    Last edited: Oct 16, 2021