How to stop the camera from clipping through mesh/walls/objects?
I'm trying to make a camera that doesn't go through walls. I have my test player run into a house but I can still see the outside of it and after trying the script on the Unity3D wiki and replacing target with my model's name, which is Basehuman01b, I still can't get it to work. I'll put a copy of the script here so hopefully someone can point out where I've gone wrong :)
The C# script:
using UnityEngine; using System.Collections;
public class SmoothCameraWithBumper : MonoBehaviour { [SerializeField] private Transform target = null; [SerializeField] private float distance = 3.0f; [SerializeField] private float height = 1.0f; [SerializeField] private float damping = 5.0f; [SerializeField] private bool smoothRotation = true; [SerializeField] private float rotationDamping = 10.0f;
[SerializeField] private Vector3 targetLookAtOffset; // allows offsetting of camera lookAt, very useful for low bumper heights
[SerializeField] private float bumperDistanceCheck = 5f; // length of bumper ray
[SerializeField] private float bumperCameraHeight = 1.0f; // adjust camera height while bumping
[SerializeField] private Vector3 bumperRayOffset; // allows offset of the bumper ray from target origin
/// <Summary>
/// If the target moves, the camera should child the target to allow for smoother movement. DR
/// </Summary>
private void Awake()
{
GetComponent<Camera>().transform.parent = Basehuman01b;
}
private void FixedUpdate()
{
Vector3 wantedPosition = Basehuman01b.TransformPoint(0, height, -distance);
// check to see if there is anything behind the target
RaycastHit hit;
Vector3 back = Basehuman01b.transform.TransformDirection(-1 * Vector3.forward);
// cast the bumper ray out from rear and check to see if there is anything behind
if (Physics.Raycast(Basehuman01b.TransformPoint(bumperRayOffset), back, out hit, bumperDistanceCheck)
&& hit.transform != target) // ignore ray-casts that hit the user. DR
{
// clamp wanted position to hit position
wantedPosition.x = hit.point.x;
wantedPosition.z = hit.point.z;
wantedPosition.y = Mathf.Lerp(hit.point.y + bumperCameraHeight, wantedPosition.y, Time.deltaTime * damping);
}
transform.position = Vector3.Lerp(transform.position, wantedPosition, Time.deltaTime * damping);
Vector3 lookPosition = Basehuman01b.TransformPoint(targetLookAtOffset);
if (smoothRotation)
{
Quaternion wantedRotation = Quaternion.LookRotation(lookPosition - transform.position, Basehuman01b.up);
transform.rotation = Quaternion.Slerp(transform.rotation, wantedRotation, Time.deltaTime * rotationDamping);
}
else
transform.rotation = Quaternion.LookRotation(lookPosition - Basehuman01b.position, target.up);
}
}
I have also tried putting colliders and rigidbody on it with no effect. I even tried the same thing but on a cube, put it so the camera was inside it(with colliders and rigidbody on the cube) and still no luck :/
Again I'm really stuck here and I would love some advice, so if you see what the issue is please don't hesitate to point it out :)
Answer by CraftyMaelyss · Jan 19, 2017 at 07:32 AM
I found out what was wrong thanks to a friend.
The script was supposed to be like this:
using UnityEngine; using System.Collections;
public class SmoothCameraWithBumper : MonoBehaviour {
[SerializeField] private Transform target = null;
[SerializeField] private float distance = 3.0f;
[SerializeField] private float height = 1.0f;
[SerializeField] private float damping = 5.0f;
[SerializeField] private bool smoothRotation = true;
[SerializeField] private float rotationDamping = 10.0f;
[SerializeField] private Vector3 targetLookAtOffset; // allows offsetting of camera lookAt, very useful for low bumper heights
[SerializeField] private float bumperDistanceCheck = 5f; // length of bumper ray
[SerializeField] private float bumperCameraHeight = 1.0f; // adjust camera height while bumping
[SerializeField] private Vector3 bumperRayOffset; // allows offset of the bumper ray from target origin
///
/// If the target moves, the camera should child the target to allow for smoother movement. DR
///
private void Awake()
{
GetComponent<Camera>().transform.parent = targetb;
}
private void FixedUpdate()
{
Vector3 wantedPosition = target.TransformPoint(0, height, -distance);
// check to see if there is anything behind the target
RaycastHit hit;
Vector3 back = target.transform.TransformDirection(-1 * Vector3.forward);
// cast the bumper ray out from rear and check to see if there is anything behind
if (Physics.Raycast(target.TransformPoint(bumperRayOffset), back, out hit, bumperDistanceCheck)
&& hit.transform != target) // ignore ray-casts that hit the user. DR
{
// clamp wanted position to hit position
wantedPosition.x = hit.point.x;
wantedPosition.z = hit.point.z;
wantedPosition.y = Mathf.Lerp(hit.point.y + bumperCameraHeight, wantedPosition.y, Time.deltaTime * damping);
}
transform.position = Vector3.Lerp(transform.position, wantedPosition, Time.deltaTime * damping);
Vector3 lookPosition = target.TransformPoint(targetLookAtOffset);
if (smoothRotation)
{
Quaternion wantedRotation = Quaternion.LookRotation(lookPosition - transform.position, target.up);
transform.rotation = Quaternion.Slerp(transform.rotation, wantedRotation, Time.deltaTime * rotationDamping);
}
else
transform.rotation = Quaternion.LookRotation(lookPosition - target.position, target.up);
}
}
When you put this script in Unity, there's some fields in the inspector that you're supposed to fill out. That and make sure the rotation of your model is set up properly(mine wasn't)
Now, in the inspector, one of the fields will say "Bumper Distance Check" This is how close an object has to be before the camera will be moved. If you go into isometric view, there will be some squares. So if you put in 15 in the "Bumper Distance Check" the camera will move away when something within 15 squares collides with it, if that makes sense.
Also this is important, make sure you name your script SmoothCameraWithBumper otherwise you might get some errors.
Answer by Chris_Payne_QS · Jan 18, 2017 at 01:31 PM
I suspect that your raycasts are hitting the player. You have presumably spotted this problem since you have a condition to ignore rays that hit the player...but if ALL your raycasts hit the player then you will never detect any obstruction. Better to put the player on a Layer and ensure the raycast excludes that Layer.
Also your wantedPosition is raised slightly in the Y, but your raycast is firing straight along the local -Z axis. That might also cause inaccurate collision detection. I'm not sure what the lerp on wantedPosition.y is for, as you are resetting wantedPosition.y every frame at the top of the function...
I actually found out that it was because the rotation and scale of the player model was waaaaay off and affected the camera, plus I wasn't meant to change anything in the script apparently P:
Answer by CandraAP · Aug 01, 2017 at 08:14 AM
I found it useful, and wanna share with you guys, Original code http://wiki.unity3d.com/index.php?title=SmoothFollowWithCameraBumper, Improvement: you need to add your target tag or target transform and ignored object tag (if necessary). C#
//(Created CSharp Version) 10/2010: Daniel P. Rossi (DR9885)
using UnityEngine;
public class SmoothCameraWithBumper : MonoBehaviour
{
[Header("[TARGET]")]
[SerializeField]
private Transform target = null; // manually assign target transform
[SerializeField] private string targetTag; //Or just insert your target tag
[SerializeField] private string[] ignoreTag; //List of ignored tags so the raycast can pass through on them
[Range(0, 5.0f)]
[SerializeField]
private float invokeUpdateRate = 0.3f;
[Header("[ADJUSTMENT]")]
[SerializeField] private float distance = 4.0f;
[SerializeField] private float height = 0.35f;
[SerializeField] private float damping = 2.0f;
[SerializeField] private bool smoothRotation = true;
[SerializeField] private float rotationDamping = 3.0f;
[SerializeField] private Vector3 targetLookAtOffset; // allows offsetting of camera lookAt, very useful for low bumper heights
[SerializeField] private float bumperDistanceCheck = 2.5f; // length of bumper ray
[SerializeField] private float bumperCameraHeight = 1.0f; // adjust camera height while bumping
[SerializeField] private Vector3 bumperRayOffset; // allows offset of the bumper ray from target origin
private void Start()
{
if (target == null) InvokeRepeating("FindTarget", 0.5f, invokeUpdateRate);
}
private void FindTarget()
{
if (target == null)
{
GameObject camTarget = GameObject.FindGameObjectWithTag(targetTag);
if (camTarget != null)
{
target = camTarget.transform;
}
}
}
private void LateUpdate()
{
if (target != null)
{
Vector3 wantedPosition = target.TransformPoint(0, height, -distance);
// check to see if there is anything behind the target
RaycastHit hit;
Vector3 back = target.transform.TransformDirection(-1 * Vector3.forward);
// cast the bumper ray out from rear and check to see if there is anything behind
if (Physics.Raycast(target.TransformPoint(bumperRayOffset), back, out hit, bumperDistanceCheck)
&& hit.transform != target) // ignore ray-casts that hit the user. DR
{
if (ignoreTag.Length > 0)
{
for (int i = 0; i < ignoreTag.Length; i++)
{
if (hit.transform.CompareTag(ignoreTag[i]))
{
return;
}
}
}
wantedPosition.x = hit.point.x;
wantedPosition.z = hit.point.z;
wantedPosition.y = Mathf.Lerp(hit.point.y + bumperCameraHeight, wantedPosition.y, Time.deltaTime * damping);
}
transform.position = Vector3.Lerp(transform.position, wantedPosition, Time.deltaTime * damping);
Vector3 lookPosition = target.TransformPoint(targetLookAtOffset);
if (smoothRotation)
{
Quaternion wantedRotation = Quaternion.LookRotation(lookPosition - transform.position, target.up);
transform.rotation = Quaternion.Slerp(transform.rotation, wantedRotation, Time.deltaTime * rotationDamping);
}
else
{
transform.rotation = Quaternion.LookRotation(lookPosition - transform.position, target.up);
}
}
}
}
[2]: /storage/temp/98463-smoothfollowwithcamerabumper.zip
Your answer
Follow this Question
Related Questions
FPS Character not moving in relation to direction/rotation 0 Answers
Smooth camera movement and lookAt [solved] 0 Answers
Smooth Camera Zoom on movement not working 3 Answers
Is my MonoDeveloped Glitchd ??? 1 Answer
Dropdown menu for camera movement 0 Answers