Search Unity

  1. Unity 2018.3 is now released.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Want more efficiency in your development work? Sign up to receive weekly tech and creative know-how from Unity experts.
    Dismiss Notice
  4. Build games and experiences that can load instantly and without install. Explore the Project Tiny Preview today!
    Dismiss Notice
  5. Want to provide direct feedback to the Unity team? Join the Unity Advisory Panel.
    Dismiss Notice
  6. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice

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:
    2
    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:
    1,824
    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:
    2
    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:
    1,824
    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:
    206
    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:
    1,824
    @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:
    206
    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:
    1,824
    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:
    1,824
    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:
    206
    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:
    1,824
    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:
    206
    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:
    1,824
    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:
    206
    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
  15. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    1,824
    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.