- Home /
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
ove 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
'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
Answer by skylem · Jan 13, 2015 at 05:01 AM
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();
}
Your answer
Follow this Question
Related Questions
Snapping to walls 1 Answer
Third person WOW like camera 1 Answer
Game object passes through walls 0 Answers
Rotating and moving the player in the direction of camera 1 Answer