Hello. I have some questions about trying to get Cinemachine to work. I implemented ‘Drifting’ as a player movement mechanic a while ago and have gotten to a point where I need to update the Cinemachine settings to work with the mechanic. The current Cinemachine camera behavior is to simply be ‘dragged along behind the player’ but we now need it to be ‘enforced behind the player’ when in the drifting player state (See the attached ‘Drifting Arc.png’ image for a top-down representation of what we’re aiming for).
A solution to force the Cinemachine free-look camera to always be to the rear of the players forward direction via the camera settings or…
A way to force the position of the Cinemachine camera on it’s orbits, via code?
The only hard-restriction for potential solutions is that the Cinemachine ‘Orbit Bindings’ cannot be changed from ‘Simple Follow With World Up’, as that breaks a TON of other stuff involving running on surfaces that the camera needs to be oriented correctly on & every other orbit binding does not satisfy the requirements. (As an example, the player could be running upside-down on the ceiling and can also initiate a drift while doing so. Every other orbit binding, other than ‘Simple Follow with World Up’, completely breaks so we cannot alter that, under any circumstances.)
To better represent what I’m trying to emulate, examine the player drifting mechanic in the following gameplay: [[/URL]
Additionally, here are the Cinemachine Free-Look camera settings that I’m currently using.
Normally I would suggest changing the binding mode only when drift is happening, by using a second FreeLook with the new settings and activating it only during drift, allowing the CM Brain to blend between them.
If that is not an option, would it be sufficient to have some code that “recenters” the FreeLook’s x-axis behind the character, overriding the player’s input on that axis?
Here is a custom extension that does that. Add it to the FreeLook. You can enable the “Recenter” property when you want recentering to occur.
using UnityEngine;
using Cinemachine;
using Cinemachine.Utility;
public class SimpleFollowRecenter : CinemachineExtension
{
public bool Recenter;
public float RecenterTime = 0.5f;
protected override void PostPipelineStageCallback(
CinemachineVirtualCameraBase vcam,
CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
{
if (stage != CinemachineCore.Stage.Body)
return;
Transform target = vcam != null ? vcam.Follow : null;
if (target == null)
return;
if (Recenter)
{
// How far away from centered are we?
Vector3 up = vcam.State.ReferenceUp;
Vector3 back = vcam.transform.position - target.position;
float angle = UnityVectorExtensions.SignedAngle(
back.ProjectOntoPlane(up), -target.forward.ProjectOntoPlane(up), up);
if (Mathf.Abs(angle) < 0.1f)
Recenter = false; // done!
else
{
angle = Damper.Damp(angle, RecenterTime, deltaTime);
Vector3 pos = state.RawPosition - target.position;
pos = Quaternion.AngleAxis(angle, up) * pos;
state.RawPosition = pos + target.position;
}
}
}
}
Thank you very much for this solution, Gregoryl! This fixed my issue and the camera now re-centers behind the player when drifting!! <3
IMPORTANT:As an additional note for anyone viewing this post in the future, ensure that your horizontal & vertical dampening on all the Top/Middle/Bottom rigs for the FreeLookCamera are all set to 0.0. I had both the Horizontal & Vertical dampening on the middle rig set to 0.5 (with the top & bottom rigs dampening values set to 0.0) and got some rapid vibrating the closer to the middle I got.
Update: So, as Gregoryl stated below, ensuring that the stuttering isn’t present despite the dampening values is the actual solution. The culprit of the continued stuttering was my attempts at rotating the player. I was directly altering the players rotation, instead of using the Rigidbodys MoveRotation() function. Doing this is not correct and interferes with the native Rigidbody interpolation. Remember kids; the API functions exist for a reason! XD (I just didn’t notice a function existed that already did what I was attempting to replicate by hand via direct assignment)
Stuttering when damping is enabled is usually an indicator that something isn’t right in the way you move the player. Most of the time it’s a problem relating to doing things in Update that you ought to be doing in FixedUpdate, or some other incorrect use of the physics API. Turning off the damping just hides the problem, which may come back to bite you later. My suggestion is to fix your motion control code so that damping no longer makes it stutter.