I am making a third person shooter. And a want the camera to follow behind the player. But i dont want the camera to pass trough walls, when the player stands with his back close to a wall. How can i achive this?
Off the top of my head:
Put a collider on the camera (sphere or box). Make sure you make a physics material with no friction, and add it to the collider (so the camera doesnt slow down when it hits, say, a wall, due to drag). Then add a script to the camera along the lines of this (psuedocode, wont actually work):
if the camera collides with something
lerp camera in Z direction towards playerObject to minimum distance from playerObject (that way camera never goes through playerObject)
if camera is at minimum distance, lerp opacity of playerObject material to 30% (so player doesnt block view of environment)
if camera exits collision
lerp camera in Z direction away from playerObject to maximum distance from player
lerp playerObject material opacity to 100%
Hope this is helpful.
The simplest answer is to just put a collision sphere around your camera, but check out the Lerps tutorial for a complete 3rd person camera system.
In the Unity Scripting Forums, there's a topic about a World of Warcraft type control scheme that might work for you. A few people worked on a problem just like this with their camera so that it won't go through walls and follows the terrain or objects that get in the way, always keeping the character in view.
Maybe It'll help you,
http://forum.unity3d.com/viewtopic.php?t=18073&highlight=wow
I tryed it, but it isn't relay the effect im looking for. I want the camera to always be directly behind the player. And only get pushed closer the the player when it collides with a wall, and only be pushed directly towards the player and not sideways. How can i achieve this result?
– HomWow camera is now located here: http://forum.unity3d.com/threads/wow-camera-movement.16949/
– MaimaiaOff the top of my head:
Put a collider on the camera (sphere or box). Make sure you make a physics material with no friction, and add it to the collider (so the camera doesnt slow down when it hits, say, a wall, due to drag). Then add a script to the camera along the lines of this (psuedocode, wont actually work):
if the camera collides with something
lerp camera in Z direction towards playerObject to minimum distance from playerObject (that way camera never goes through playerObject)
if camera is at minimum distance, lerp opacity of playerObject material to 30% (so player doesnt block view of environment)
if camera exits collision
lerp camera in Z direction away from playerObject to maximum distance from player
lerp playerObject material opacity to 100%
Hope this is helpful.
The code for this is simple:
Have your camera code track the desired location behind the player (where the camera should be if there are no obstructions), the desired location is not necessarily where you want the camera to be on a given frame. Rather you calculate the position between the desired location and the player that is unobstructed by any walls using a Raycast or RaycastAll (depending on whether or not you'll potentially have multiple obstructing objects between the camera and player).
Here's some sample c# code:
RaycastHit hit;
Vector3 targetPosition;
if (Physics.Raycast(desiredPosition, playerTransform.position - desiredPosition, out hit, (playerTransform.position - desiredPosition).magnitude, wallLayers))
{
targetPosition = (hit.point - playerTransform.position) * 0.8f + playerTransform.position;
/*
Note that I move the camera to 80% of the distance
to the point where an obstruction has been found
to help keep the sides of the frustrum from still clipping through the wall
*/
}
else
{
targetPosition = desiredPosition;
}
In the sample code:
desiredPosition is the world space position that the unobstructed camera would be placed at
playerTransform is the Transform component of the player character the camera is following
wallLayers is a LayerMask that contains the layer with all of the wall colliders in it
targetPosition is the point in world space that the Camera will actually be moved to.
targetPosition = (hit.point - playerTransform.position) 0.8f + playerTransform.position; not really sure what to do with this line of code is not even valid code...
– BarasI found the easiest fix for this! If you use the standard FPS Controller, just go to the camera and under Clipping Planes, change the property : Near to 0.01!!! And it’s fixed, just saw it a while ago, Easy as 1… 2… 3!! Hope it helps!
-Roman
The correct way would be to:
- Determine where would you ideally have your camera if there were no walls
- Raycast the world from your player (or camera focus point) to the desired camera position, with the ray max. length equals the distance from focus to desired point.
- Simply put the camera at the raycast hit point if it hit something: raycast gives you distance result. So simple formula is: camPos = focusPos + rayDirection*(hitDistance - wallOffset); add wallOffset so the camera doesn’t end up stuck right on the wall, but slightly further of it
Try this, I tested it a couple times and it works well
(In case the camera mistakes the player as an object, use the inverse on the layermask variable)
The First script is the camera script that detects the object that hits the camera
The normal point is the original point of the camera;
Player max is the distance of the player from the camera
public Transform NormalPoint, PlayerMax, ThCam;
public float moveSpeed;
public float distance;
public CameraTriggerFix CTF;
public int layerMask = (1 << 8);
void Update()
{
distance = Vector3.Distance(ThCam.position, PlayerMax.position);
Vector3 fwd = transform.TransformDirection(Vector3.forward);
if (Physics.Raycast(this.transform.position, fwd, 10))
{
CTF.gameObject.GetComponent<Collider>().enabled = true;
ThCam.position = Vector3.Lerp(ThCam.position, PlayerMax.position, moveSpeed * Time.deltaTime);
print("There is something in front of the object!");
}
else
{
CTF.gameObject.GetComponent<Collider>().enabled = false;
ThCam.position = Vector3.Lerp(ThCam.position, NormalPoint.position, moveSpeed * Time.deltaTime);
}
}
Attach the camera script to the camera then add a sphere collider to the cam, check isTrigger to true and a rigid-body and make sure to set gravity to false. After you’ve done that, add the next script underneath this to the camera. This script improves the accuracy and the how long the camera has to stay on that object.
public CameraProtectionScript CHD;
public bool Enter;
private void OnTriggerEnter(Collider other)
{
if (other.tag != "Untagged")
{
CHD.ThCam.position = Vector3.Lerp(CHD.ThCam.position, CHD.PlayerMax.position, CHD.moveSpeed * Time.deltaTime);
Enter = true;
CHD.enabled = false;
}
}
private void OnTriggerStay(Collider other)
{
if (other.tag != "Untagged")
{
CHD.ThCam.position = Vector3.Lerp(CHD.ThCam.position, CHD.PlayerMax.position, CHD.moveSpeed * Time.deltaTime);
Enter = true;
CHD.enabled = false;
}
}
private void OnTriggerExit(Collider other)
{
if (other.tag != "Untagged")
{
CHD.enabled = true;
Enter = false;
this.GetComponent<Collider>().enabled = false;
}
}
Hope this helps ;)!
© 2022 - 2024 — McMap. All rights reserved.
Could you give me a link to the Lerps tutorial you are referring to?
– Hom