I have been working out a physics based character controller and am about 90% there; however, for the past day I’ve been trying to solve this one particular issue with my follow camera in a literal ‘edge case’.
When the SphereCast hit returns a contact normal that is near perpendicular to its’ cast direction, I get an odd flickering movement of my camera position. It seems to be happening at an angle between 80 to 90 degrees (been a tad difficult to nail it down), so I believe the SphereCast method I am using needs to have some way to pre-evaluate the contact normal and if it is near perpendicular… perhaps smooth the transform position in either a positive or negative direction. (I hope that makes sense).
I’ve illustrated the issue here and a snapshot of an orthographic view of my test case which shows the debug.draw lines of the contact normals against the surface.
here’'s some source I’ve been mucking with:
void FixedUpdate()
{
targetRotation = LookAtTarget.rotation;
Quaternion currentRotation = Quaternion.Lerp(previousRotation, targetRotation, _damp * Time.deltaTime);
previousRotation = currentRotation;
reverseLookat = transform.position - LookAtTarget.position; //gets vector from control to camera
distance = reverseLookat.magnitude; //get distant
direction = reverseLookat / distance; //normalized direction
transform.position = LookAtTarget.position; //begin calc of camera position based on "follow" target
CameraContact = Physics.SphereCast(LookAtTarget.position, _safetyZone, direction, out CameraHit, deltaDistance, layerMask); //cast 'thick' ray between control and camera to check for possible collisions
if (!CameraContact)
{ //do normal camera rotation and maintain distance
transform.position -= currentRotation * Vector3.right * deltaDistance;
}
else
{ //a collision will occur adjust camera
transform.position -= currentRotation * Vector3.right * CameraHit.distance; //shorten 'deltadistance' of camera to follow target
Debug.DrawRay(CameraHit.point, CameraHit.normal, Color.red, 500); //draw contact normal on hit surface
Debug.Log("angle: " + Vector3.Angle(LookAtTarget.position - transform.position, CameraHit.normal)); // what is the angle between contact normal and direction vector
}
transform.position += currentRotation * Vector3.up * deltaHeight; //keep camera slightly above target for 3rd person view
transform.LookAt(LookAtTarget, LookAtTarget.TransformDirection(Vector3.up)); //maintain verticle position aligned with lookat target using worldup 'hint'
}
As can be seen in the screen shot, the red debug.draw lines stop at an angle that would be perpendicular to the direction vector of which the SphereCast lays out. It is within a few degrees of this contact angle, that the camera jumps between its’ prefered deltaDistance, and the adjusted distance (the distance between the contact and origin) causing an odd jumping/flickering.
I’ve attempted to Lerp between the distances by pre-evaluating the transforms, but I could not get it working. So I thought I would ask if someone who has seen or delt with this, may have some suggestions on the best way to adjust the camera in this edge case?
