hi finding it very hard to get a result I’m after - thought this was a relatively simple scenario but the camera just won’t behave. perhaps someone can suggest a set up that might work. I’ve currently got a Clear shot setup with a Main (red) and Above (blue) camera (positioned at highest potential point) but it’s not working, the camera occasionally moves closer when blocked etc. and also yaw rotation (how do I limit rotation to only one axis? the damping set to full still doesn’t stop it) Here’s a diagram of what I’m after:
The camera should only pitch, no yaw or roll. Again works mostly but then occasionally it will yaw - I need the pitch rotation only so can’t turn off the Aim.
The camera should ALWAYS remain on the z axis it’s set on (it should attempt to climb the Y to get the shot ONLY- if it can’t see then too bad, it’s blocked). I can not get this to work - the Collider priority to ‘get it in shot’ overrides every attempt to stop the camera moving forward (and the Collider is necessary to detect the blockage?). I’ve tried the 2D and 3D confiner (a flat 3D collider seems better than a 2D one… but it just spins). Every setting to Preserve Camera Distance. Camera Distance set everywhere. But it will still move forward to get the shot. Adding a Aim Hard Look At and a Confiner makes the camera spin uncontrollably and also move outside of the confiner (above the target or spinning inside the confiner)…actually basically any Aim makes it spin.
The camera should use the Framing Transposer so the softzone moves the camera when in it either X or Y - it should ‘mainly’ be parallel on the y and z axis, offset to a FIXED z axis.
When the view is blocked the camera should give up gracefully not jitter like a mad dog
A Dolly track doesn’t move up and down the Y and it also yaw rotates - alos note that the ‘ball’ can go below the y =0 to below etc so camera needs full freedom on Y axis.
Any pointers would be appreciated of how to break this down into components and get the basic restraints happening. I thought even a single Virtual Camera should be able to handle this situation but can’t figure it out.
The single VCam with Framing Transposer works fine for the basic follow (with no Aim) - it’s the blocked view scenerio I’m trying to solve - my main issue is the camera not being restrained when the view is blocked and moving right next to object
If I understand this correctly then you just want a FramingTransposer plus some specialized handling to move the camera when the view to the target is obstructed.
That specialized handler should only move the camera vertically, while adjusting the tilt to keep the target in the center of the frame.
Is that correct?
If so, can you elaborate on how you expect the camera to choose which vertical direction to move in when it wants to resolve an occlusion? And is there a limit to how much it should try to move?
The main issue is that if the view is blocked in my current setup the camera will move right in to the avatar, then ‘mostly’ it will move back out and find the top camera viewpoint.
Here’s my current setup - I’m using the Transposer as the Framing Transposer plus the Lock to Target creates an infinite spin. AFAIK the Transposer works like a rubber band effect from a centre point rather than a rectangular dead/soft zone setup? I’d prefer the Framing version.
For the rotation I can see that some rotation along the z axis maybe necessary for a damping follow effect but yes primarily along the x axis (tilt), moving up and down the Y to find the view - vertical movement scan priority. At the moment I’m just trying to get that to work - I might try a ‘below’ camera view later if I can get this working.
In terms of vertical Y limit - arbitrary - say 10 relative! but ability to set a limit yes (and then look up from that point to aim at target). That’s the other thing - if it can’t find a view move or stay at the last point where it could see something rather than constantly jittering to try to get the shot within it’s constraints. some ‘lookahead time plus a give up if can’t find’
Let me know if this isn’t clear
Building the constraint system is where I’m stuck - ie how to layer constraints and behaviours the right way - I guess like the Unity Execution Cycle. I don’t understand for instance why the Framing Transposer and Lookat plus Constraint results in an infinite spinning loop, or why the without the constraint it moves to above the target and then spins… I guess it requires a deep dive into the code to really understand but some workflow guidelines would be useful.
Also you mention ‘specialized’ - I thought this scenario was fairly common and some combo of the built-in components could do it but if it does require custom code - in order to create that I think I’d also need a fairly good understanding of why it’s failing at the moment? ie maybe where to override behaviour?
I am still confused, and I don’t feel like you answered my question. Forget all the stuff you’ve tried, and the potential solutions. I just want to know the behaviour you’re seeking, so that I can understand the issue.
If you just put a Framing Transposer on the vcam - nothing else, no confiners, colliders, hardlookats, clearshots, dolly tracks - does it behave the way you want, except in the situation where there is an occluding object?
In the case of an occluding object, do you want the camera to just move upwards on the Y axis, while tilting its aim downwards to keep the target in view, until it can see the target or a maximum distance is reached?
EDIT: note that Transposer and Framing Transposer are different things. You seem to be confusing them. I am asking specifically about Framing Transposer.
Yes, the Framing Transposer follows the avatar with the soft zones triggering movement correctly. Without a Collider the view is obstructed as you’d expect.
Yes, a smooth transition to a unobstructed viewpoint, prioritising the +Y axis (only the Y and X, no Z movement) and not moving from the fixed Z axis the camera is travelling on (which is offset from the avatar at a fixed distance). I realise ‘some’ rotation on the Y axis to slightly angle the camera as it peeks around the obstruction before moving up would be necessary to create smooth movement to the higher viewpoint, so maybe not -only- pitch but other axis would be heavily damped.
Also the camera must ‘give up’ if it can’t find a view - I don’t want it moving to some far point on the X axis where it can see the object from the side. It should try moving up to a certain height (say 10) and then if there are no viewpoints, give up and remain at the ‘most smooth’ interpolation between the last view point and the X position.
The first post has an image with the intended setup - the thick blue line where the cameras are represents the fixed Z offset (Z axis is left to right, X is front to back, Y up and down - that may have been confusing sorry - the camera in game is looking down the Z axis just the image shows the setup from the side to describe it). The box is an obstruction where the camera move to a higher point on the Y axis and looks down to see object. Maybe in the future this Z axis would be a confiner volume with a bit of movement back and forth, but for the meantime I’m just trying to get the camera to stay on the Z offset.
(I’ve attached an update image with some more labelling - the red line indicates the desired path when there’s an obstruction. The second image shows a blue line that goes through the box - that’s what currently happens with a Collider - it gets blocked, moves really close and then backs off to the higher position)
Thanks for the clarification. I think I understand now what you want.
With CM out of the box and some simple scripting, we can get something that comes pretty close. The only thing that’s a little tricky is dynamically finding a camera offset (top, left, or right) that is just enough to resolve the occlusion. If you’re willing to settle for cameras at certain fixed distances from the base camera, then it is easy. I’ve attached a test scene to demonstrate. When you open it, press play and in the scene view drag the player from side to side, and observe the game view to see the camera behaviour as the player goes past some obstacles.
The camera rig is a ClearShot wrapping static cameras representing the base camera position and several standard offsets from it. The priorities of the child cameras determine the preference: base view is preferred, followed by top view, and then side views. You can add more views at greater distances if you like, setting the priorities accordingly.
The CInemachineCollider is only used to evaluate shot quality; it does not move the camera. The rig itself has a custom behaviour that tracks the player at a fixed Z position, with damping.
Hi thanks for all your attention on this. I imported your example into a fresh project (2021.3.39f1 and CineMachine 2.10.0 BTW) - two videos inside the ZIP attachment as I can’t upload videos.
The setup is similar to where I ended up going - the Avoid Obstacles check box seems to be vital to stopping the ‘get closer’ behaviour so that’s good to know - one difference I could see. With that checked I found the Collider component does move the camera. If I checked that in your example it gave me the problem I was grappling with - flickering in/out of Z beofre finding the top camera.
The example had a couple of the problems I was grappling with
when the player is moving quickly the priority skips to the closest camera
when the player is occluded the the main camera, the top camera still isn’t being made active, at the end of the first video I move to the occluded position and solo the top camera which can clearly see the player but isn’t chosen.
I tweaked the settings a bit a get a lot closer to the behaviour I’m after so I think can consider this ‘good enough’ until I bump into the edge cases!
discovered the colliders extended beyond the object boundaries… so I reset them and with the Minimum distance of 0.2 got the 2nd result which is what I was after - you added them as a buffer to trigger the camera position I presume? so I’ve found putting them back to scale 1 gives better result…? (ie moves up when occluded)
And Blend time to 2 to reduce the skipping during fast movement, also smoother curved transitions
Priorities to more extreme difference between left/right and up/down. I presume these are weighted and not just linear?
I would like to try and get the Framing Transposer behaviour working to reduce camera movement when player is in ‘live zone’ and not move the camera so much. You’ve removed that altogether - is that because it won’t work in this scenario? Would I have to custom create the live/soft/dead zone response manually?
I don’t know what you mean. “priority skips to the closest camera” doesn’t make sense to me. There are some settings in the ClearShot and CinemachineCollider that control how long to wait before switching cameras (to avoid rapid switching when you’re whizzing by stuff), and the minimum time to hold a camera before switching to another one. You can tweak those.
I can’t repro that. It’s fine when I try it. I don’t know whether you changed any settings in your test. Make sure that the children of the ClearShot all have “Always” in the Standby Update setting. Probably the ClearShot itself should have that also.
Next time, just send me the scene itself. You can export it to a unitypackage like I did.
I have no idea what you’re talking about. In my scene, the colliders are the same size as the objects. If you play with them the wrong way, you can unsync them. Maybe you did that.
The purpose of the “Minimum Distance From Target” setting is to avoid detecting the target itself as an obstacle. The collider will ignore any obstacle that is closer than this distance to the target point. Generally, you want to set it to be just slightly larger than the target’s radius.
Here is how the priorities work: if more than one child camera has a clear view of the target, it will choose from among them the child with the biggest priority. That’s it.
I would discourage that, it will cause you endless grief. Better to augment CameraRig.cs to implement a dead zone. It’s easy: just don’t move it if it’s closer than some specified distance from the target.
using UnityEngine;
public class CameraRig : MonoBehaviour
{
public Transform Target;
public float CameraPosZ = 0;
public float Damping = 0.2f;
public float DeadZoneSize = 1.0f;
Vector3 m_Velocity;
// Use LateUpdate to be sure that the target has already moved
void LateUpdate()
{
// Follow the target on the XY plane, with damping
var targetPos = Target.position;
targetPos.z = CameraPosZ;
// Implement a dead zone: don't move the camera if the target is in the dead zone
var pos = transform.position;
var distance = Vector3.Distance(pos, targetPos);
if (distance > DeadZoneSize)
{
var dir = (targetPos - pos) / distance;
targetPos = pos + dir * (distance - DeadZoneSize); // just go up to the dead zone's edge
transform.position = Vector3.SmoothDamp(pos, targetPos, ref m_Velocity, Damping);
}
}
}
Here’s a video of me importing your package into a totally new 3D project - the colliders are set at 2. How that happened I don’t know but I did import it twice beforehand when you first uploaded as I wasn’t sure. So that’s caused some confusion - with those colliders the Collision doesn’t work, so resetting them to 1 seems to get us on the same page.
For the priority thing, I was asking about how say items of same priority would be selected and ideas of ‘quality’ are used - “The Cinemachine ClearShot Camera component chooses among its children Virtual Cameras for the best quality shot of the target”
So in terms of weighting I was saying if there were 2 cameras with views of the objects but one was slightly occluded but I would actually prefer that camera then by adding priority I could compensate for the lower quality due to occlusion and choose that camera over the ‘clear shot’.
Many thanks for the tips and code it has definitely helped me get on track. Also shown that some custom coding is probably necessary earlier than I thought.
Yes, I see that the colliders were off when you imported. How strange. Maybe it’s a Unity version thing - I exported using 2022.3.
For the ClearShot, shot quality is the first sort, so higher quality shots will win, regardless of priority. If multiple shots have the same quality, then priority resolves that. If multiple shots have the same quality AND the same priority, then ClearShot just makes an arbitrary choice.
The current shot quality algorithm does not take partial occlusion into account. It does a simple raycast to the target point (in the test scene, that would be the center of the player sphere). Occluded is bad, not-occluded is good. If you set the “optimal target distance” setting to nonzero, then some additional calculation happens that increases the quality assessment as the target approaches that optimal distance from the camera.
Because the CinemachineCollider extension is on the ClearShot itself, its settings are shared by all the child cameras. If you remove the extension and instead add one to each of the child cameras, then you can have separate settings for each.
If you upgrade to CM3 (you can’t unless you also upgrade Unity to at least 2022.3) then you will have the option of coding your own custom shot quality evaluator.
Great thanks for the additional details (import maybe a Unity Bug bug then). Won’t be upgrading from 2021.3 for this project so I’ll stick with CM2 for the moment and look forward to unwrapping all the nice new features at a later date.