Stop camera from going trough walls

I am making a third person shooter. And a want the camera to follow behind the player. But i dont want the camera to pass trough walls, when the player stands with his back close to a wall. How can i achive this?

Off the top of my head:

Put a collider on the camera (sphere or box). Make sure you make a physics material with no friction, and add it to the collider (so the camera doesnt slow down when it hits, say, a wall, due to drag). Then add a script to the camera along the lines of this (psuedocode, wont actually work):

if the camera collides with something

lerp camera in Z direction towards playerObject to minimum distance from playerObject (that way camera never goes through playerObject)

if camera is at minimum distance, lerp opacity of playerObject material to 30% (so player doesnt block view of environment)

if camera exits collision

lerp camera in Z direction away from playerObject to maximum distance from player
lerp playerObject material opacity to 100%

Hope this is helpful.

I found the easiest fix for this! If you use the standard FPS Controller, just go to the camera and under Clipping Planes, change the property : Near to 0.01!!! And it’s fixed, just saw it a while ago, Easy as 1… 2… 3!! Hope it helps!

-Roman

In the Unity Scripting Forums, there's a topic about a World of Warcraft type control scheme that might work for you. A few people worked on a problem just like this with their camera so that it won't go through walls and follows the terrain or objects that get in the way, always keeping the character in view.

Maybe It'll help you,

http://forum.unity3d.com/viewtopic.php?t=18073&highlight=wow

The code for this is simple:

Have your camera code track the desired location behind the player (where the camera should be if there are no obstructions), the desired location is not necessarily where you want the camera to be on a given frame. Rather you calculate the position between the desired location and the player that is unobstructed by any walls using a Raycast or RaycastAll (depending on whether or not you'll potentially have multiple obstructing objects between the camera and player).

Here's some sample c# code:

RaycastHit hit;
Vector3 targetPosition;

if (Physics.Raycast(desiredPosition, playerTransform.position - desiredPosition, out hit, (playerTransform.position - desiredPosition).magnitude, wallLayers))
{
    targetPosition = (hit.point - playerTransform.position) * 0.8f + playerTransform.position;
    /* 
       Note that I move the camera to 80% of the distance
       to the point where an obstruction has been found
       to help keep the sides of the frustrum from still clipping through the wall
    */
}
else
{
    targetPosition = desiredPosition;
}

In the sample code:

  • desiredPosition is the world space position that the unobstructed camera would be placed at

  • playerTransform is the Transform component of the player character the camera is following

  • wallLayers is a LayerMask that contains the layer with all of the wall colliders in it

  • targetPosition is the point in world space that the Camera will actually be moved to.

try this:- http://blockmonkey.com/my-work/unity-3d-work/

The correct way would be to:

  1. Determine where would you ideally have your camera if there were no walls
  2. Raycast the world from your player (or camera focus point) to the desired camera position, with the ray max. length equals the distance from focus to desired point.
  3. Simply put the camera at the raycast hit point if it hit something: raycast gives you distance result. So simple formula is: camPos = focusPos + rayDirection*(hitDistance - wallOffset); add wallOffset so the camera doesn’t end up stuck right on the wall, but slightly further of it

Try this, I tested it a couple times and it works well :wink:

(In case the camera mistakes the player as an object, use the inverse on the layermask variable)

The First script is the camera script that detects the object that hits the camera

The normal point is the original point of the camera;
Player max is the distance of the player from the camera

public Transform NormalPoint, PlayerMax, ThCam;
public float moveSpeed;
public float distance;
public CameraTriggerFix CTF;

public int layerMask = (1 << 8);

void Update()
{

    distance = Vector3.Distance(ThCam.position, PlayerMax.position);

    Vector3 fwd = transform.TransformDirection(Vector3.forward);

    if (Physics.Raycast(this.transform.position, fwd, 10))
    {
        CTF.gameObject.GetComponent<Collider>().enabled = true;
        ThCam.position = Vector3.Lerp(ThCam.position, PlayerMax.position, moveSpeed * Time.deltaTime);
        print("There is something in front of the object!");
    }
    else
    {
        CTF.gameObject.GetComponent<Collider>().enabled = false;
        ThCam.position = Vector3.Lerp(ThCam.position, NormalPoint.position, moveSpeed * Time.deltaTime);
    }
}

Attach the camera script to the camera then add a sphere collider to the cam, check isTrigger to true and a rigid-body and make sure to set gravity to false. After you’ve done that, add the next script underneath this to the camera. This script improves the accuracy and the how long the camera has to stay on that object.

 public CameraProtectionScript CHD;
    public bool Enter;


    private void OnTriggerEnter(Collider other)
    {
        if (other.tag != "Untagged")
        {
            CHD.ThCam.position = Vector3.Lerp(CHD.ThCam.position, CHD.PlayerMax.position, CHD.moveSpeed * Time.deltaTime);
            Enter = true;
            CHD.enabled = false;
        }
    }

    private void OnTriggerStay(Collider other)
    {
        if (other.tag != "Untagged")
        {
            CHD.ThCam.position = Vector3.Lerp(CHD.ThCam.position, CHD.PlayerMax.position, CHD.moveSpeed * Time.deltaTime);
            Enter = true;
            CHD.enabled = false;
        }
    }

    private void OnTriggerExit(Collider other)
    {
        if (other.tag != "Untagged")
        {
            CHD.enabled = true;
            Enter = false;
            this.GetComponent<Collider>().enabled = false;
        }
    }

Hope this helps ;)!

The simplest answer is to just put a collision sphere around your camera, but check out the Lerps tutorial for a complete 3rd person camera system.