Free look camera with world space binding and overriden world up

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.

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?

I am using CM 2.2.7.

When binding is set to WorldSpace it looks like this (even with world up override is set):
Imgur
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:
Imgur
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.

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.

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:

[SerializeField]
private Transform _worldSpaceOverride;
public Transform WorldSpaceOverride {
   get { return _worldSpaceOverride; }
   set { _worldSpaceOverride = value; }
}

public Vector3 CameraUp {
   get { WorldSpaceOverride ? WorldSpaceOverride.up : Vector3.up; }
}

public Vector3 CameraForward {
   get { WorldSpaceOverride ? WorldSpaceOverride.forward : Vector3.forward; }
}

public Vector3 CameraRight {
   get { WorldSpaceOverride ? WorldSpaceOverride.right : Vector3.right; }
}

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): vacantviciousantarcticgiantpetrel

@OhiraKyou This is exactly what we have in CinemachineBrain:

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

Put your player in that field. Does it not work for you?

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: HarmfulShockingAmericanriverotter

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.

Here is a sample gif showing it in action (sorry for the low color res)

3942526--337312--worldup.gif

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.

Well, the world up override does for me what you describe you need. See my gif above. What are you doing that’s different?

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.

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?

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:
BigTenseFlea

1 Like

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.

I see you’re using Kinematic Character Controller, yes? :slight_smile: 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…

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.

1 Like

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:
informalhopefulblackwidowspider

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.

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!