I started to use Cinemachine and I want to know if there’s a way to make the camera recenter to target when, for example, the spacebar is pressed. What I mean is make the same thing the option “Recenter to target heading” does, but when a key is pressed.
What I thought is to make a call to the method that’s called when “Recenter to target heading” is enabled, so I’ve been searching in the Cinemachine scripts and what I got so far is to, indeed recenter the camera but only when I keep pressed the button, when I release the spacebar the camera movement stops in place.
I just added a condition inside AxisState.cs that checks if the spacebar is pushed:
public void DoRecentering(ref AxisState axis, float deltaTime, float recenterTarget)
{
if (Input.GetButton("RecenterCamera")) {
if (!m_enabled && deltaTime >= 0)
return;
recenterTarget = axis.ClampValue(recenterTarget);
if (deltaTime < 0)
{
CancelRecentering();
if (m_enabled)
axis.Value = recenterTarget;
return;
}
float v = axis.ClampValue(axis.Value);
float delta = recenterTarget - v;
if (delta == 0)
return;
if (CinemachineCore.CurrentTime < (mLastAxisInputTime + m_WaitTime))
return;
// Determine the direction
float r = axis.m_MaxValue - axis.m_MinValue;
if (axis.m_Wrap && Mathf.Abs(delta) > r * 0.5f)
v += Mathf.Sign(recenterTarget - v) * r;
// Damp our way there
if (m_RecenteringTime < 0.001f)
v = recenterTarget;
else
v = Mathf.SmoothDamp(
v, recenterTarget, ref mRecenteringVelocity,
m_RecenteringTime, 9999, deltaTime);
axis.Value = axis.ClampValue(v);
}
}
I know it maybe not be the correct place to put that condition. I’m pretty new to Unity, just used to make avatars on vrchat and I tried to make a Visual Novel while ago, so I’m not very experienced with how code works. Sorry for my english too, I’m not a native speaker.
You should not be modifying AxisState.cs - that’s part of Cinemachine and you will lose your ability to upgrade easily if you start modifying it. Also AxisState is used in several places, probably the spacebar checking is not wanted in those other places.
Instead, add a custom script to your vcam that sets the m_Enabled member of the recentering component inside your vcam, according to whether or not the spacebar is pressed.
Yup, at first I thought that I should create a new script and manage that variable there, but I couldn’t get access to that variable (I don’t really know how). How can I set that variable? I have a GameObject with the FreeLook camera on it, but I have no clue on how to get it on code. Getting the component of that GameObject gives me this error:
I’m not sure what Cinemachine component you’re using. I’ll assume for now that it’s a CinemachineFreeLook. In that case, you would create a custom script, add it to that FreeLook. Then the code would be something like this:
Note that once the condition is triggered (e.g. spacebar is presssed) you would probably want a little logic in there to hold recentering enabled until the recentering time has elapsed, and maybe cancel it if the user moves the mouse.
This morning I was trying out your code and now everything is working! I finally understood how the GetComponent works and I could recenter everything perfectly (the X and Y, because I noted that the RecenterToTargetHeading was just recentering the X axis).
With a bit of work I added too that conditions, and everything is working fine. Maybe is not as smooth as it should, but for me is a great start.
Heya, just wondering if you might be able to share your final code on this? I have been trying to get the FreeLook camera to re-centre behind the player on button press as well and just cant get it to work! Would really appreciate it if you could share your work!
Hey Meguchi, I have a (eh, it works) solution implemented…though I’m looking for something a little better.
Using new Unity’s new input manager to fire UnityEvents on some button press to recenter the camera:
public void OnCenterCamera(InputAction.CallbackContext context)
{
_camera.m_RecenterToTargetHeading.m_enabled = true;
_camera.m_YAxisRecentering.m_enabled = true;
// Disable the camera centering after it completes
// so it doesn't stay locked
// Multiply the completion timeout for some padding
int completionTimeout = (int) _camera.m_RecenterToTargetHeading.m_RecenteringTime * 1000; // 0.25 *1000
Task.Delay(completionTimeout * 2).ContinueWith(t => {
_camera.m_RecenterToTargetHeading.m_enabled = false;
_camera.m_YAxisRecentering.m_enabled = false;
});
}
Main issue is completionTimeout (m_RecenteringTime) is more of a max speed from what I’ve gathered rather than the actual time it takes to smoothly transition the camera’a position to its “centered” state.
Could you elaborate?
I tried creating my own recentering functionality by caching the starting m_XAxis, and m_YAxis values, then lerping back to them when the player presses a button, but because those aren’t consistent, as the objective my camera is to snap directly behind my player, that idea didn’t go very far. I’m not sure I see which values always correspond to whether or not a FreeLook camera’s centered to the target heading.
The Y axis recentered value is 0.5. The X axis value would depend on your binding mode. If it’s LockToTarget (or one of the variants), then “behind the player” would be 0. If it’s WorldSpace, then “behind the player” would be the difference in Y rotation between player forward and world forward. If it’s SimpleFollow then the desired recenter value would be the Y rotation difference between camera forward and player forward - note that this will change every frame, as the camera moves. You’re recentered when that difference is sufficiently small.