stop camera from going through walls

I know it’s been asked before, and i didn’t find a good answer so i am asking it again, how to stop camera from entering walls in a 3rd person shooter game… if you have played Manhunt or even Gta Sa, you’ll find it smoothly lerps above or very close to the Player…

i don’t like the idea of collider + physics material, it didn’t work as i wanted… and i did make my own code… it casts a ray at the front, checks if player is hit, and moves forward or else raycasts at back and adjusts the position at the player’s back…

it works… but there are 3 problems i’m having:

  1. it works only AFTER the camera has actually entered the wall (In Manhunt 1 and Gta games, the camera AVOIDS the walls altofether)

(I did try Collider + smooth physics material) WITH and WITHOUT my raycasting code, but it’s not helpful

  1. At certain Angles, the Raycasting doesn’t work, maybe it’s just my Editor’s POV, but it looks like it’s in already.

  2. my raycasting code makes the camera shake obviously because it’s getting [hit…not hit… hit… not hit…] conditions match back and forth)

I’m still unable to solve this issue, there’s no smooth avoidance of the walls, do you have any better approach to solving this?

Thanks

Okay, i solved this, for anyone who might face this problem in the future, there are 2 ways to solve this:

  1. Read code from 3rd person character controller + fly mode from asset store and read the DoubleViewPosCheck function in ThirdPersonCamOrbit script file (this one is a bit complicated and the camera is NOT a child of the Player in this project)

  2. Use my method:

    float raycastDistance = 15f;

    float spherecastDistance = 5f;

    float sphereRadius = 2f;

    float speedToFixClipping = 0.2f;

    void FixClippingThroughWalls ()
    {

    RaycastHit hit;
    
    Vector3 direction = transform.parent.position - transform.position;
    
    Vector3 localPos = transform.localPosition;
    
    
    for (float i = offset.z; i <= 0f; i += speedToFixClipping)
    {
    	Vector3 pos = transform.TransformPoint (new Vector3 (localPos.x, localPos.y, i));
    	if ( Physics.Raycast (pos, direction, out hit, raycastDistance))
    	{
    		if (!hit.collider.CompareTag ("Player"))
    			continue;
    		
    		if (!Physics.SphereCast (pos, sphereRadius, _transform.forward * -1, out hit, spherecastDistance)) {
    			localPos.z = i;
    			break;
    		}
    	}
    }
    transform.localPosition = Vector3.Lerp (transform.localPosition, localPos, smoothing * Time.deltaTime);
    

    }

Code Explanation: It’s pretty simple, we store the local position in a local variable and just use a for loop to reduce the local z position – from Camera’s predetermined Z offset (-3.7f) (Read NOTE) down to 0f, at each iteration we just raycast from the front (to make sure the Player is in front of the Camera) and a spherecast from the back (raycast causes more jerking), we settle at a position where the Player is in front and there is NO collider hit at the back …

NOTE: The Camera is a child of Pivot Point which is child of the Player in my character, you might need to tweak the radius and spherecast distance to prevent jerking of Camera.

The Pivot Point’s LocalPosition is: 0f, -0.3f, 0f and the Camera’s Local Position is: 0f, 1.6f, -3.7f in my case, in case you’ve a different local distance, you’ll need to tweak those to fix the jerking…

Intelligent camera behaviour is complicated, and I highly doubt you’re going to get a definitive answer on a Q&A style site like this. Bear in mind that games like GTA often have a programmer dedicated to doing nothing other than programming the camera.

The following Gamasutra article is nearly 6 years old, but still contains a lot of useful alternative you might want to consider: Real-Time Cameras - Navigation and Occlusion

Ez Pz, Just change the field of view in the camera’s inspector.