Third Person Camera Can See Through Walls!

To start, I am following a tutorial on making a third person game. you can find the tutorial here if you’re interested.


The Thing I want to do

move the camera closer to the player when it collides with the wall. or some other professional looking effect. (Ideally like dark souls for example)


My Camera Code

using UnityEngine;

using System.Collections;

[RequireComponent (typeof (BarsEffect))]
public class ThirdPersonCamera : MonoBehaviour 
{


	#region Variables (private)

	// Inspector serialized
	[SerializeField]
	private float distanceAway;		// offset y axis
	[SerializeField]
	private float distanceUp;		// offset z axis
	[SerializeField]
	private float smooth;		// time to get to targetPosition below
	[SerializeField]
	private Transform playerTransform;		// Where the player is moving FEET
	[SerializeField]
	private Vector3 offset = new Vector3 (0f, 1.5f, 0f);
	[SerializeField]
	private float camSmoothDampTime = 0.1f;
	[SerializeField]
	private float wideScreen = .2f;
	[SerializeField]
	private float targetTime = 0.5f;

	// Private global only
	private Vector3 targetPosition;		// Where gameCam wants to be
	private Vector3 lookDir;
	private Vector3 currentCamSmoothVelocity = Vector3.zero;
	private BarsEffect barEffect;
	private CamStates camState = CamStates.Behind;

	// Hashes
	

	#endregion

	#region Properties (Public)

	public enum CamStates
	{
		Behind,
		FirstPerson,
		Target,
		Free
	}

	#endregion

	#region Unity event functions

	void Start ()
	{
		playerTransform = GameObject.FindWithTag ("player").transform;
		lookDir = playerTransform.forward;

		barEffect = GetComponent<BarsEffect> ();
		if(barEffect == null)
		{
			Debug.LogError("attach a widescreen BarsEffect script to the camera", this);
		}
	}

	void LateUpdate ()
	{
		Vector3 characterOffset = playerTransform.position + offset; //camera is looking at feet + offset

		lookDir = characterOffset - this.transform.position;
		lookDir.y = 0f;
		lookDir.Normalize ();
		Debug.DrawRay (this.transform.position, lookDir, Color.green);

		targetPosition = characterOffset + playerTransform.up * distanceUp - lookDir * distanceAway;
//		Debug.DrawRay (playerTransform.position, Vector3.up * distanceUp, Color.red);
//		Debug.DrawRay (playerTransform.position, -playerTransform.forward * distanceAway, Color.blue);
		Debug.DrawLine (playerTransform.position, targetPosition, Color.magenta);

		compensateForWalls (characterOffset, ref targetPosition);

		smoothTransition(this.transform.position, targetPosition);

		transform.LookAt (playerTransform);
	}

	#endregion

	#region Methods

	private void smoothTransition (Vector3 fromPos, Vector3 toPos)
	{
		this.transform.position = Vector3.SmoothDamp (fromPos, toPos, ref currentCamSmoothVelocity, camSmoothDampTime);
	}

	private void compensateForWalls(Vector3 fromObject, ref Vector3 toTarget)
	{
		Debug.DrawLine (fromObject, toTarget, Color.cyan);

		RaycastHit wallHit = new RaycastHit ();
		if(Physics.Linecast(fromObject, toTarget, out wallHit))
		{
			Debug.DrawRay(wallHit.point, wallHit.normal, Color.red);

			Vector3 wallHitVector3 = new Vector3 (
				wallHit.point.x,
				wallHit.point.y,
				wallHit.point.z);

//			float distance = 0f;
//
//			switch (wallHit.normal)
//			{
//			case Vector3.left:
//
//			}

			toTarget = new Vector3 (wallHitVector3.x , toTarget.y, wallHitVector3.z );		
		}
	}

	#endregion
	
}

My Player controller logic

using UnityEngine; 
using System.Collections;


public class CharControlLogic : MonoBehaviour 
{


	#region Variables (private)

	// Inspector serialized
	[SerializeField]
	private Animator animator;		// reference to char anim
	[SerializeField]
	private float DirectionDampTime;	// Used to smooth the tranistion between animations
	[SerializeField]
	private GameObject gameCam;
	[SerializeField]
	private float directionSpeed;	
	[SerializeField]
	private float rotationDegreePerSecond = 120f;

	// Private global only
	private float speed;		// how much the joystick is moved in any diection
	private float direction;
	private float leftX;
	private float leftY;
	private string tagHorizontal;		// Input.getaxisraw hori.
	private string tagVertical;		// Input. getAxisRaw vert.
	private string tagSpeed;
	private string tagDirection;
	private string tagGameCam;
	private AnimatorStateInfo stateInfo;

	// Hashes
	private int m_LocomotionId = 0;

	#endregion

	#region Properties (Public)

	

	#endregion

	#region Unity event functions

	void Start ()
	{
		InitializeInputAxes ();

		animator = GetComponent<Animator> ();

		if (animator.layerCount >= 2)
		{
			animator.SetLayerWeight(1,1);
		}

		m_LocomotionId = Animator.StringToHash ("Base Layer.Locomotion");

		gameCam = GameObject.FindWithTag (tagGameCam);

	}

	void FixedUpdate ()
	{

		if (animator)
		{
			stateInfo = animator.GetCurrentAnimatorStateInfo(0);

			// pull values from the controller
			leftX = Input.GetAxisRaw(tagHorizontal);
			leftY = Input.GetAxisRaw(tagVertical);

			DirectionalInputToWorldSpace(this.transform, gameCam.transform, ref direction, ref speed);

			animator.SetFloat(tagSpeed, speed);
			animator.SetFloat(tagDirection, direction, DirectionDampTime, Time.deltaTime);

			/// attempt to make it so the character runs a circle around the camera, instead of a circle-like curve

			if(IsInLocomotion() && ((direction >= 0 && leftX >= 0) || (direction < 0 && leftX < 0)))
			{
				Vector3 rotationAmount = Vector3.Lerp(Vector3.zero, new Vector3 (0f, rotationDegreePerSecond * (leftX < 0f ? -1f : 1f), 0f), Mathf.Abs(leftX));
				Quaternion deltaRotation = Quaternion.Euler(rotationAmount * Time.deltaTime);
				this.transform.rotation *= deltaRotation;
			}

		}
	}

	#endregion

	#region Methods

	void InitializeInputAxes()
	{
		tagHorizontal = "Horizontal";
		tagVertical = "Vertical";
		tagSpeed = "Speed";
		tagDirection = "Direction";
		tagGameCam = "MainCamera";
	}

	void DirectionalInputToWorldSpace(Transform target, Transform camera, ref float directionOut, ref float speedOut)
	{
		Vector3 targetDir = target.forward;
		
		Vector3 inputDir = new Vector3 (leftX, 0f, leftY);

		speedOut = inputDir.sqrMagnitude;

		// camera rot.
		Vector3 camDir = camera.forward;
		camDir.y = 0f;
		Vector3 relativeDir = Vector3.forward;
		Quaternion referentialShift = Quaternion.FromToRotation (relativeDir, camDir);

		// convert directional input to world-space coordinates
		Vector3 moveDir = referentialShift * inputDir;
		Vector3 axisSign = Vector3.Cross (moveDir, targetDir);

		Vector3 debugElevatedTargetTransformVector3 = target.position;
		debugElevatedTargetTransformVector3.y += 2f;

		Debug.DrawRay (debugElevatedTargetTransformVector3, moveDir, Color.green);
		Debug.DrawRay (debugElevatedTargetTransformVector3, axisSign, Color.red);
		Debug.DrawRay (debugElevatedTargetTransformVector3, targetDir, Color.magenta);
		Debug.DrawRay (debugElevatedTargetTransformVector3, inputDir, Color.blue);

		float angleTargetToMove = Vector3.Angle (targetDir, moveDir) * (axisSign.y >= 0 ? -1f : 1f);
		angleTargetToMove /= 180f;

		directionOut = angleTargetToMove * directionSpeed;
 	}

	private bool IsInLocomotion ()
	{
		return stateInfo.nameHash == m_LocomotionId;
	}


	#endregion
	
}

Synopsis of my struggles

I’ve been pulling my hair out trying to figure out how to basically make a collider without making a collider (it feels like anyway).
I am primarily a java/c# programmer (just in my free time), so, basically, I know how to program. I’m not very familiar with unity however.


the method i am playing with is the compensateforwalls method at the end of the camera class



u could raycast from your camera this would create a u can then access this raycasts Hit as a transform then determine your cameras Vector3.distance from this point and if your camera gets to close to it then it gains a + to its forward position

// the section after out is ur actual contact point and the if is optional you could have this cast constantly.
// then comes ur distance check
// then compare the distance to see if u need to push the camera
// you could also use Quaternion.LookRotation to determine a push direction from the hitpoint

    RaycastHit hit = new RaycastHit();
    if (Physics.Raycast(transform.position, out hit,fwd, 10)) {
         float thedistance = Vector3.distance(transform.position, hit.point.transform.position);
}

    if(thedistance < 2) {
     PushCamera();
    }