I’m trying to make a 2.5D top down game (like Don’t starve). Here’s my current setup:
Main Camera perspective is set to Perspective, here’s how Virtual Cam looks like:
Rotation is -30 to have angled look; follow offset -13 is basically camera distamnce from the ground, on Playmode it sets to the same -13 in virtcam position and to -9.75 on the maincam.
It’s all good until the player gets close to the upper or lower part of the boundaries, then the main camera starts to zoom in/out respectively (which pisses me off tbh). I tried to lock main cam transform.pos.z but since it depends on virtual cam, it didnt work. And virt cam ALWAYS stays at -13 in the inspector.
Also tried all sorts of combinations of virt cam’s body and binding mode (and confiner extension) to no result. I was thinking of checking (in the script) if main camera’s z pos starts changing and change vcam body to DoNothing, but then the camera won’t follow player horizontally.
So is there a way to make virt cam not mess with main cam z position?
Try putting Framing Transposer in Body, and Do Nothing in Aim. That will keep the camera angle fixed at whatever you set it, and will make the camera move (not rotate) to follow the player.
Next, to prevent the camera from tracking the player vertically, add a vertical dead zone to the Framing Transposer.
1 Like
Thanks for looking into this, I made a small video to better illustrate the prob:
Here’s my attempt (one of many) implementing what you said:
First I made so that character stays in the center by adjusting the offset (maybe thats the problem);
then added dead zone height, didn’t help much;
added dead zone depth, almost worked but things went very wrong on going north.
And on reactivating camera went very weird.
Try adding this custom extension. Set the Z Position value to what you need.
You could extend the script to lock the Y position as well, if needed.
using UnityEngine;
using Unity.Cinemachine;
/// <summary>
/// An add-on module for Cinemachine Camera that locks the camera's Z co-ordinate
/// </summary>
[SaveDuringPlay] [AddComponentMenu("")] // Hide in menu
public class LockCameraZ : CinemachineExtension
{
[Tooltip("Lock the camera's Z position to this value")]
public float ZPosition = 10;
protected override void PostPipelineStageCallback(
CinemachineVirtualCameraBase vcam,
CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
{
if (stage == CinemachineCore.Stage.Body)
{
var pos = state.RawPosition;
pos.z = ZPosition;
state.RawPosition = pos;
}
}
}
1 Like
Hmm, it doesn’t quite work, Im afraid. The Z position does set Z pos of virt cam, but main camera still does whatever it feels like. I tried both Transposer and Framing Transposer.
Also ‘Unity.Cinemachine’ namespace didn’t work for me, ‘Cinemachine’ did. Should I update it? I’m still on 2.10.3, could that be the reason it doesn’t work?
For CM2, just change the namespace in the script as you suggest, it will work.
Forget Transposer - use only Framing Transposer.
main camera still does whatever it feels like
That makes no sense. Are you sure you have just the one vcam in the scene? Any other weirdness in your hierarchy?
1 Like
Another vid:
The scene is very simple; should point out if Dead zone height is 0, the cam zooms like before. It feels a bit different with 2, but kinda weird, not quite sure what’s going on.
Maybe we should take a step back and reconsider the approach.
2D Confiners don’t work very well when the camera is aimed obliquely at them.
If you only want the camera to move horizontally, maybe a better idea is to use a Dolly camera. Make a horizontal track at the desired distance and position.
1 Like
So here’s what I did: made a new virt cam with a collider, made it a tracked dolly with auto dolly on.
Then made a dolly track with 2 waypoints from left to right, so it matched the collider (for some reason I can’t see dolly as a gizmo, it’s probably smth I messed up in the settings). It kinda works, the transition is slightly noticeable, but it works. Also the dolly cam has a slight delay while tracking player, but I haven’t messed with its settings yet.
Gotta say, it’s quite a hassle to have 2 extra cameras for every scene and to align dolly tracks accordingly. Assuming I haven’t overcomplicated the process.
The default transposer worked great, it’s weird it moves camera like that, I’d think you’d have to enable something to make it happen. Thanks for all suggestions, I’ll leave it till tomorrow.
PS i did some thinking and instead of all that crap above, it can be just one dolly cam. But I’m too baked to implement it now
Still wrecking my brain, dolly cam not quite working out, until I can think of a better implementation.
For now I decided to update CInemachine to 3, need a little help. I used to do this
CinemachineCore.Instance.GetActiveBrain(0).ActiveVirtualCamera.VirtualCameraGameObject.
GetComponent<CinemachineVirtualCamera>().
GetCinemachineComponent<CinemachineBasicMultiChannelPerlin>().m_AmplitudeGain = force;
to get current active vcam and amplitude of noise component. I checked documentation, but still can’t find a way to do this.
I get that there’s CinemachineBrain instead of Core and it’s static, and GetCinemachineComponent is obsolete. But I can’t get object out of ActiveVirtualCam. How would that line look now?
So to save my sanity I’ve decided to redesign north and south exits of scenes, so they are basically narrow paths with virtual cameras, that track nothing. So once the player is there, it’s pretty much a static cam. From testing it looks less janky of all solutions so far (dolly had weirdness on reaching left or right spline).
Im not sure if I need ver3 now, but I’m still curious how to redo the code in my previous post.
Upgrading is probably a good idea. Did you see the general guide here?
https://docs.unity3d.com/Packages/com.unity.cinemachine@3.1/manual/CinemachineUpgradeFrom2.html
For your specific question, you can do
if (brain.ActiveVirtualCamera is CinemachineCamera cam)
{
// do stuff with cam
if (cam.TryGetComponent<CinemachineMultiChannelPerlin>(out var noise))
{
// do stuff with noise
}
}
1 Like
Thanks, yeah i’ve seen the guide. I’ll post the corrected the code if anyone needs it:
private void CameraShake(float force)
{
var brain = CinemachineBrain.GetActiveBrain(0);
if (brain.ActiveVirtualCamera is CinemachineCamera cam)
{
if (cam.TryGetComponent(out CinemachineBasicMultiChannelPerlin noise))
noise.AmplitudeGain = force;
}
}
One last question on my initial problem: if i’d use 3D Confiner and have a specific mesh (like a 3D trapezoid) for a scene, would that work? I don’t think I’d do that, just curious.
Yes, that would probably work, but it would take some doing to get the shape just right.
1 Like
I FINALLY got it right. Very simple really, instead of 2D confiner i used a 3D one and a simple box coll (why was I thinking mesh?) to confine camera. Here’s how it looks from top down in 2d:
The camera was still fluctuating a bit on z, adding custom LockZ extension made it super stable. Thanks for all the help!
1 Like