- Home /
How do I make my camera not clip through walls?
I don't want my camera script to rotate or do anything special because I have that handled all ready. All I want is my camera's position to scale depending on how close it is to the wall.
How I want my camera script to work in 2 ways:
I want my Camera to change its position based on what surface it collided with(I have this accomplished)
I want my camera to scale its position based on how closely it is to the wall(Main problem).
My scene:
My script(the bit with /* is my attempt at the problem)
using UnityEngine;
using System.Collections;
public class CameraScript : MonoBehaviour
{
public int count;
private Vector3 Campos;
public Transform player;
public GameObject Player;
public int RayDistance = 10;
[HideInInspector]
public GameObject Wall;
public void Start()
{
// if (Campos == null)
// {
Campos = new Vector3(0f, 5f, -15f);
// }
}
void FixedUpdate()
{
//if (connection)
transform.position = Player.transform.position + Campos;
transform.LookAt(player);
}
public void Update()
{
/*RaycastHit hit;
Ray LandingRay = new Ray(transform.position, Vector3.back);
if (Physics.Raycast(LandingRay, out hit, RayDistance))
{
Wall = hit.collider.gameObject;
float dist = Vector3.Distance(hit.point, transform.position);
Debug.Log("distance = " + dist);
if (dist <= 2)
{
//Camera math stuff
//Btw tell me step by step how it works so Ik how to make a script like this in the future
}
}
*/
if (count == 0)
{
Campos = new Vector3(0f, 5f, -15f);
// Debug.Log(count);
Player.transform.eulerAngles = new Vector3(0f, 0f, 0f);
}
else
{
if (count == 1)
{
Campos = new Vector3(15f, 5f, 0f);
// Debug.Log(count);
Player.transform.eulerAngles = new Vector3(0f, 270f, 0f);
}
else
{
if (count == 2)
{
Campos = new Vector3(0f, 5f, 7f);
//Debug.Log(count);
Player.transform.eulerAngles = new Vector3(0f, 180f, 0f);
}
else
{
if (count == 3)
{
Campos = new Vector3(0f, 8f, 15);
//Debug.Log(count);
Player.transform.eulerAngles = new Vector3(0f, 90f, 0f);
}
else
{
if (count <= -1)
{
count = 3;
}
else
{
if (count <= 4)
{
count = 0;
}
//the script is going to account for the ceiling position and floor position so don't worry about that
}
}
}
}
}
}
}
So, I just want a improvised version of my current script but I want it to scale its position based on how close it is to the wall. I've been trying this for a week so I am clueless on how to do this by my self...
Edit: Here is the script I forgot to mention that effects camera(sorry >_< )
using UnityEngine;
using System.Collections;
public class Dash : MonoBehaviour {
public GameObject Previouscollided;
private GameObject collided;
public LayerMask Wall;
Vector3 newPosition;
public GameObject Wall1;
public GameObject Wall2;
public GameObject Wall3;
public GameObject Wall4;
public GameObject Floor;
public GameObject Ceiling;
public GameObject RecentWall;
public int speed;
void Start ()
{
newPosition = transform.position;
}
// Update is called once per frame
void Update ()
{
if (Input.GetMouseButtonDown(0))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if(Physics.Raycast(ray, out hit, Wall.value))
{
collided = hit.collider.gameObject;
RecentWall = collided;
//Debug.Log(collided);
Cameraposition();
collided.layer = LayerMask.NameToLayer("Ignore Raycast");
newPosition = hit.point;
Previouscollided.layer = LayerMask.NameToLayer("Wall");
Previouscollided = hit.collider.gameObject;
//Debug.Log(Previouscollided);
}
}
if (collided == Wall1)
{
transform.position = Vector3.Lerp(transform.position, newPosition + new Vector3(0, 0, -2f), speed * Time.deltaTime);
}
if (collided == Wall2)
{
transform.position = Vector3.Lerp(transform.position, newPosition + new Vector3(0, 0, 2), speed * Time.deltaTime);
}
if (collided == Wall3)
{
transform.position = Vector3.Lerp(transform.position, newPosition + new Vector3(-2, 0, 0), speed * Time.deltaTime);
}
if (collided == Wall4)
{
transform.position = Vector3.Lerp(transform.position, newPosition + new Vector3(2, 0, 0), speed * Time.deltaTime);
}
if (collided == Floor)
{
transform.position = Vector3.Lerp(transform.position, newPosition - new Vector3(0, 0, 0), speed * Time.deltaTime);
}
if (collided == Ceiling)
{
transform.position = Vector3.Lerp(transform.position, newPosition - new Vector3(0, 0, 0), speed * Time.deltaTime);
}
}
public void Cameraposition()
{
if(collided == Wall1)
{
GameObject theCamera = GameObject.Find("Main Camera");
CameraScript cameraScript = theCamera.GetComponent<CameraScript>();
cameraScript.count = 0;
}
if (collided == Wall2)
{
GameObject theCamera = GameObject.Find("Main Camera");
CameraScript cameraScript = theCamera.GetComponent<CameraScript>();
cameraScript.count = 1;
}
if (collided == Wall3)
{
GameObject theCamera = GameObject.Find("Main Camera");
CameraScript cameraScript = theCamera.GetComponent<CameraScript>();
cameraScript.count = 2;
}
if (collided == Wall4)
{
GameObject theCamera = GameObject.Find("Main Camera");
CameraScript cameraScript = theCamera.GetComponent<CameraScript>();
cameraScript.count = 3;
}
if (collided == Floor)
{
GameObject theCamera = GameObject.Find("Main Camera");
CameraScript cameraScript = theCamera.GetComponent<CameraScript>();
cameraScript.count = 4;
}
if (collided == Ceiling)
{
GameObject theCamera = GameObject.Find("Main Camera");
CameraScript cameraScript = theCamera.GetComponent<CameraScript>();
cameraScript.count = 5;
}
}
}
What do you mean by "I want my camera to scale its position based on how closely it is to the wall." ? What is your expected behavior when the camera gets closer to the wall?
Scaling a position does not make much sense unless you change the camera's parent scale, then it will have impact the camera's position if the local translation is not at (0,0,0).. but I don't think that's what you meant..
Also, what is the purpose of your count variable? Is it used to represent the closest wall? It feels like some of your code is missing, as it's always staying at 0. (Also, using a switch here, would make things much more easy to read). Like this:
switch(count)
{
case 0:
Campos = new Vector3(0f, 5f, -15f);
Player.transform.eulerAngles = new Vector3(0f, 0f, 0f);
break;
case 1:
Campos = new Vector3(15f, 5f, 0f);
Player.transform.eulerAngles = new Vector3(0f, 270f, 0f);
break;
case 2:
//etc..
}
sorry I took awhile to respond and thank you to being the first person to try to put a meaningful solution and so I will clarify. The Way count works is when I click on one of the walls on the scene the camera switches its position so if I clicked on say Wall1 I will have my camera switch positions so it is facing at the player and away from wall 1 etc etc... Also, for scaling depending how close my camera is to the wall. I mean I want my camera to be closer/farther from the wall depending on how close the player is to the wall but I don't want it to clip because the way the script works currently The camera changes position according to player position but it doesn't account for the wall behind it so it clips through.
I want my camera to work like the script in this tutorial. I tried to follow this tutorial but it has extra functions for orbiting and he adds parts to his script out of video so.(https://www.youtube.com/watch?v=$$anonymous$$kbovxhw$$anonymous$$4I)
Well, you could calculate the first intersecting point behind the camera and then use a ratio (lerp) between that point and the player's position. That way the camera would always stay between the player and the wall behind it and would move away from the wall as the player move away from it.
You'd probably have to cap that lerp distance though, as I'm not sure you would want this behavior when the camera is far from a wall.
Answer by abdullahsyyd · Mar 14, 2017 at 05:51 AM
@dragonking300 You can improve this by using Physics.Linecast , it can help you to detect anything coming between cube and camera. Linecasting from camera will help you detect any hurdles between target and camera then you can translate your camera position according to detection.
I have no clue how to do that mathematically + I can't improve my script with extra features if I can't get the core ones to work...
Answer by ifdef_ben · Mar 15, 2017 at 11:09 PM
If you put colliders on your walls you could do something like this:
//inside camera class
Vector3 CalculateCameraPosition(float maxLerpDist = -1f)
{
Vector3 result = transform.position;
//here put a ratio between 0 and 1.
//0.8 means the camera will be place at 80% of the distance between the player and the wall.
float ratio = 0.8f;
//We start a ray cast originating from the player position, in the direction facing the back of the camera
Ray ray = new Ray(player.transform.position, -transform.forward);
RaycastHit rayHit;
//Looking for the wall behind the camera
if(Physics.Raycast(ray, out rayHit))
{
//We calculate the distance between the player and the intersecting wall behind the camera and get 80% of the distance by multiplying the ratio.
float distance = (Player.transform.position - rayHit.point).magnitude * ratio;
//If we do not set a maxLerpDist or if the maxLerpDist is set and superior to the distance.
if(maxLerpDist < 0 || distance < maxLerpDist)
{
//we place the result at 80% of the distance between the player and the wall
result = Vector3.Lerp(Player.transform.position, rayHit.point, ratio);
}
}
return result;
}
This is a function that returns a position vector, you put it like every other function in your class.. And you call it to get a position between the wall and the player.. That you could then apply to the camera using for instance "Transform.Position = CalculateCameraPosition();"...
What should I do if the camera is outside of the wall tho(I'll be experimenting while I wait)
I tried this but if the camera gets to close to the wall it becomes a first person camera :/
void FixedUpdate()
{
ImprovisedCameraPosition = Vector3.Lerp(PreviousCampos, Campos, speed);
transform.position = Player.transform.position + ImprovisedCameraPosition;
transform.LookAt(player);
transform.position = CalculateCameraPosition(Campos.magnitude);
}
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Camera that follows rotating object with mouse input 0 Answers
How do I make a coroutine from another script stop? 3 Answers