it’s having a hard time resolving within a confined space
are there magic settings you’ve found that handle elegantly camera movement without wobbling, popping or going inside things it shouldn’t?
The CM collider extension simply resolves collisions and line-of-sight obstructions. It’s not a motion planner. If you have a tight space and want elegant camera movement within that space, the CM Collider won’t necessarily do that job. What you need is perhaps more like a vcam on a navmesh. It would be an interesting area to explore.
That’s an idea…
is there a way to wrangle that into the CM system: a navmesh constraint
Maybe author a custom extension that does the motion planning. Input would be vcam’s desired position (as it is for the CM collider). Extension would make sure that vcam only moves smoothly on the navmesh towards its target position.
Are you a coder or an artist? (they are not mutually exclusive :))
Artist, I can wrangle some programming. Where is a simple example of extension?
You can look at CinemachineCameraOffset.cs.
The main method to override is PostPipelineStageCallback. The “state” param contains the target vcam position (state.CorrectedPosition). You can add a delta to state.PositionCorrection to alter the vcam’s position.
The extension will need to store its own state because it will want a reference to a navmesh, and will probably need some concept of velocity to avoid popping.
How I would do it the old way:
have a navmesh agent with stop distance set to mindistance2target and a low priority and a large radius like 1m so that whenever another creature rams into it the camera gets moved naturally
the navmesh agent has the camera on top of it and that camera is pointing at the target
when the target is beyond maxdistance then call SetDestination(targetposition)
so yeah this would look at the butt of the creature a lot unless the target is in front of the creature then the cameraman is always running in front, dodging whatever obstacle comes its way… yeah that’d work well
so what i need is target position and then i can calculate distance and also call the SetDestination to it. i looked at the offsetextension and that PostPipelineStageCallback doesn’t seem to have stage.targetposition or state.targetposition.
and how do i get the vm to just chill and let the navmesh agent do the moving?
state.ReferenceLookAt is the lookAt target position.
Yeah, you can just forget about the extension, and make an invisible navmesh agent to follow your target, and then make a simple vcam that follows the navmesh agent and looks at the target. Easy-peasy
I made a Body instead and it looks pretty good.
it dodges others, avoids walls and feels like the cameraman is lurking in this biome which is a very neat feeling so thank you for the suggestion.
It’s not elegant because it uses a hierarchy but i can’t be bothered making a full fledged micro agent in the body script and i like the default behavior of navmeshagent which aut brakes and has good control over acceleration. Maybe you know where the source code for the navmeshagent is on github (if at all, it could be native code)
now onto the problems:
as i’m converting all my cams to that i run into a problem with blend who doesn’t want to accept the camera
see how vm cam reverts to none when i add it to the top list?
i think it’s a bug where blend only accepts direct children instead of traversing the hierarchy.
it’s definitely not making life easy so
i think it’s that bit which is nuking non direct children, it’s very arbitrary behavior. i tried removing that but packages are readonly so if you could fix that on your end, that’s be nice
when clicking solo it’s complaining that the agent isn’t on the navmesh, i think it’s because bodies are executed at editor mode when solo is on
how do i turn off executeineditmode for this body? extensions have that but not body
using System;
using Cinemachine.Utility;
using UnityEngine;
using UnityEngine.AI;
namespace Cinemachine
{
[DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)]
[AddComponentMenu("")] // Don't display in add component menu
[SaveDuringPlay]
public class CinemachineNavmeshTransposer : CinemachineComponentBase
{
public NavMeshAgent agent;
public float height=1;
public float maxDistanceToTarget;
public override bool IsValid => true;
public override CinemachineCore.Stage Stage => CinemachineCore.Stage.Body;
public override float GetMaxDampTime() => 0;
public override void MutateCameraState(ref CameraState curState, float deltaTime)
{
if (Vector3.Distance(transform.position, FollowTargetPosition) > maxDistanceToTarget)
agent.SetDestination(FollowTargetPosition);
curState.RawPosition = agent.transform.position + Vector3.up*height;
curState.ReferenceUp = Vector3.up;
}
public override void ForceCameraPosition(Vector3 pos, Quaternion rot)
{
base.ForceCameraPosition(pos, rot);
agent.Warp(pos);
}
}
}
Very nice!
The child-only thing in BlendList is not a bug, it’s by design, so we can’t change that. If you want you can make a custom version of BlendList by copying it into your project and changing the copy. But why not just accept the restriction and make the navmesh vcam a child?
You can’t turn off ExecuteInEditMode for vcam components. Instead you can add some code to check for Application.isPlaying, and don’t query the navmesh unless it is.
Also, I would add a check for VirtualCamera.PreviousStateIsValid, and warp the position if it’s false.
ok done, it’s flat now. why this design?
like that?
It’s because parent/child relationships among vcams have special meaning.
Not quite. Moving to the destination using the navmesh is analogous to damping. PreviousStateIsValid==false is a signal that we don’t want to damp our way to the destination, we want to go there instantly. So in this case you should set the agent’s destination and position to FollowTargetPosition.
which is?
you’ve lost me, if i set the agent’s position it’s warping meaning i’m not using the agent’s quality of movement or pathfinding which includes collision ← i need that to avoid stepping on monsters, i’m only sampling the navmesh as a way to avoid going inside walls.
Parent/child relationship of vcams signifies whole ownership. A child vcam is a slave of its parent, and is not exposed to the outside world. If a BlendList had a child vcam that itself had child vcams, the BlendList should see the child, but not the grandchilden.
Right. Then you can query the navmesh for the nearest legal point to the destination, and put the vcam there. The idea is that it should reach its destination instantly if PreviousStateIsValid==false.