You’re currently checking if its just hitting something. You need to do something like a Hit.Distance check and figure out how far away you want that camera to be.
I have some code that will work for you, however I should mention that this Camera I have is underneath a prefab and gets the local position within that prefab. Also these values should be tweaked to your purposes. I’m still having issues with the code, and trying to get the camera to update position faster. If you move very fast, you can still clip through walls, and moving backwards into a wall can still be choppy on occasion.
Quick Run Down of this code.
It sounds out four raycasts. It checks backwards and sides. If it detects collision on the sides and backwards, it will move in at the set speed.
There is also the fourth raycast which is set for the transform.up ray, this detects vertical collision and will move the camera down if it detects something above it (the ceiling)
I pass in a Vector 3 StartPos, which is where the Camera is at the very start of the scene.
On start I tell it to get the LocalPosition, if you’re unfamiliar with this, it is the position within the GameObject I have it under. So the hierarchy has my camera object set up as PlayerController (has all the movement as well as the rigidbody) → Camera and other objects are the Child of the player controller. This way I can avoid a pesky camera follow script.
So if you don’t have the camera set up as the Child of whatever you’re moving around, this code will not work for you.
RayHit : My Raycast
RayHit.Distance: When it checks for a collision, this returns the distance away from the collision
RayHitDistance can then be passed in to an If Statement. For instance I have it checking against how far away I want the camera to be before it starts moving.
so,
if(RayHit.Distance < .5f)
//Move Forward
This would make it so that if the Raycast (RayHit) detects collision that is .5 meters away, it will start moving the camera backwards.
I also have it check, for the moving back into position, you want to make sure that it doesn’t indefinitely keep moving forward. So in order to combat this, I wrote in the Vector 3 StartPos. This works only because of the way I have the camera Childed underneath another GameObject which moves our camera around in the scene.
else if (transform.localPosition.z > StartPos.z && RayHit.distance > .8f)
//Move Back
We have this code working by checking first that we’re no longer moving forward using the Else before the If. Then we check the position relative to where we want the camera to be. So since the previous check moves the camera Forward on the Z Axis, we know that our values will be greater than the values we got from StartPos. So we check this against the StartPos.Z, and if its greater than that, and we’re further than 8.f meters away, we’ll go ahead and move our camera back into position, and it will keep moving until our camera transform is no longer greater than StartPos.Z
I need to make sure you understand this code before copy pasting. So thats really how it works, now here’s the rest of the code that I used in order to get this to at least Function. (Still not perfect code)
Vector3 StartPos; //Camera position at start
void Start()
{
StartPos = transform.localPosition; //Gets the camera position within the prefab at the start of the game. Local position is position as child object of another object
}
// Update is called once per frame
void Update()
{
CameraCall(); //Calls to the camera movement function
}
void CameraCall() //The function handling camera movement back into position, handles the raycast as well
{
RaycastHit RayHit; //The name within this script of our raycast
Debug.DrawRay(transform.position, -transform.forward, Color.red, .001f); //draws the raycast in the scene so we can make sure its working properly
Debug.DrawRay(transform.position, transform.right, Color.red, .001f);
Debug.DrawRay(transform.position, -transform.right, Color.red, .001f);
if ((Physics.Raycast(transform.position, -transform.forward, out RayHit, 10f, 3, queryTriggerInteraction: QueryTriggerInteraction.Ignore)) ||
(Physics.Raycast(transform.position, transform.right, out RayHit, 10f, 3, queryTriggerInteraction: QueryTriggerInteraction.Ignore)) ||
(Physics.Raycast(transform.position, -transform.right, out RayHit, 10f, 3, queryTriggerInteraction: QueryTriggerInteraction.Ignore))) //sends out raycast and returns bool value
{
if (RayHit.distance < 0.5f) //Default value .25f for this check, and .1f for the movement, .5f also works well
{
//transform.localPosition += new Vector3(0, 0, .05f); //SpeedMult * Time.deltaTime); //moves the camera closer to the player on collision with wall
transform.localPosition += new Vector3(0, 0, .1f);
}
else if (transform.localPosition.z > StartPos.z && RayHit.distance > .8f) //Default value .35f, and .1f for the movement .8f works well
{
transform.localPosition -= new Vector3(0, 0, .05f); //SpeedMult * Time.deltaTime); //Moves the camera back into position// .05f works very well
}
}
if (Physics.Raycast(transform.position, transform.up, out RayHit, 10f, 3, queryTriggerInteraction: QueryTriggerInteraction.Ignore))
{
if (RayHit.distance < 0.65f)
{
transform.localPosition -= new Vector3(0, .005f, 0); //SpeedMult * Time.deltaTime); //moves the camera closer to the player on collision with wall
}
else if (transform.localPosition.y < StartPos.y && RayHit.distance > .65f) //Checks to make sure that the camera doesn't go further than original position, also checks for raycast distance from wall
{
transform.localPosition += new Vector3(0, .005f, 0); //SpeedMult * Time.deltaTime); //Moves the camera back into position
}
}
}