I hope I’ve posted on the right place!
My problem is: I have to implement a 3rd person game but I have to get rid of object occlusion between the camera and my character. The camera is placed right behind the character which is moving around in my scene, if I go backwards and then hit a wall with the camera, the camera will pass through it and I can’t see anything… or even if I’m turning aroundand the camera finishes behind a wall or another object, my view is compromised.
Is there any algorithm to get rid of this? I mean, something that moves the camera in another position (forward, higher, on the shoulder…) to prevent this? I found some articles about camera control here: http://cameracontrol.org/blog/bibliography/
The state of the art article tells something about the various approaches… has anything like that been developed by someone on unity?
Or, which is the best approach for you?
Do a RayCast from target pos back to the intended camera position - if you hit anything along the way, push the camera forward to that point.
The Boot Camp demo does this.
Well thank you for the answer!
Actually is it possible to put a cone or a cylinder between the camera and the character just to enlarge the radius of the controlled zone, to avoid even partial obstructions? (eg when passing through a door and the edge cuts the scene viewed by the camera)
Or, better, instead of pushing the camera forward, could it be an idea moving it around the character in order to avoid the obstacole?
Well I use a straight SphereCast - new in Unity3 - as just casting a ray actually is not good enough - forgot that.
The radius of the sphere should be something close to the near plane value of your camera.
Ok, I tried with SphereCast but the results aren’t as I hoped
the code is shown below (I merged the code for a smooth follow of the object with the code for collision detection):
the hierarcy is object → camera
// The target we are following
var target : Transform;
// the height we want the camera to be above the target
var height = 5.0;
// speed
var heightDamping = 2.0;
var rotationDamping = 3.0;
//camera collision variables
var maxDistance = 5.0;
var minDistance = 1.2;
var smooth = 8.0;
private var dollyDir;
private var distance;
// Place the script in the Camera-Control group in the component menu
@script AddComponentMenu("Camera-Control/Smooth Follow")
function Awake()
{
dollyDir = transform.localPosition.normalized;
distance = transform.localPosition.magnitude;
}
function Update ()
{
// Early out if we don't have a target
if (!target)
return;
//collision policy
//ideal camera position
var desiredCameraPos:Vector3;
var targetDirection:Vector3;
desiredCameraPos= transform.parent.TransformPoint( dollyDir * maxDistance );
targetDirection = target.transform.position - transform.position;
targetDirection = transform.InverseTransformDirection(targetDirection.normalized);
var hit:RaycastHit;
var collisionFlag =Physics.SphereCast( desiredCameraPos, 0.5, targetDirection, hit, maxDistance );
//to avoid the continuous collision granted when the camera gets too close to my object
if( collflag hit.collider.gameObject.transform != target)
{
var d;
d = Mathf.Clamp( hit.distance, minDistance, maxDistance );
distance = Mathf.Lerp(distance,d,Time.deltaTime*smooth);
}
else
{
distance=Mathf.Lerp(distance,maxDistance,Time.deltaTime*smooth);
}
//camera movement policy
// Calculate the current rotation angles
wantedRotationAngle = target.eulerAngles.y;
wantedHeight = target.position.y + height;
currentRotationAngle = transform.eulerAngles.y;
currentHeight = transform.position.y;
// Damp the rotation around the y-axis
currentRotationAngle = Mathf.LerpAngle (currentRotationAngle, wantedRotationAngle, rotationDamping * Time.deltaTime);
// Damp the height
currentHeight = Mathf.Lerp (currentHeight, wantedHeight, heightDamping * Time.deltaTime);
// Convert the angle into a rotation
currentRotation = Quaternion.Euler (0, currentRotationAngle, 0);
// Set the position of the camera on the x-z plane to:
// distance meters behind the target
transform.position = target.position;
transform.position -= currentRotation * Vector3.forward * distance;
// Set the height of the camera
transform.position.y = currentHeight;
}
I sweep a sphere from the desired camera position to my object, if any collision occours, then I push the camera towards the object.
It works very random… I mean, when I get close to a wall, in some point the camera goes towards the object, but if I rotate my object, still keeping the collision, the script no longer notice it and brings the camera back, even behind the wall.
var collisionFlag =Physics.SphereCast( desiredCameraPos, 0.5, targetDirection, hit, maxDistance );
starting from the camera to the object… I tried also from the object to the camera but no success…
(the object i’m moving around is a sphere with a ray of 2, and to test the collisions I put some walls on a terrain and i’m moving around the sphere with the keyboard…)
With physics.linecast all is fine, though if my object goes half behind a wall, I can’t see the whole scene from the object’s POV but the wall covers half of my sight, obviously.
Physics.Linecast( transform.parent.position, desiredCameraPos, hit );
Why linecast works almost perfectly while spherecast do not? Drawing a parallelepiped around my object and then casting rays towords the vertexes to detect obstacles between object and camera could be a solution?
Hi Mugan, I’m developing a system in unity that solves the problem you have as a research project.
It is able, not only, to ensure that the object is visible, but also that it is at a certain position on the screen and other photographic parameters.
I have not yet release it, but my will is to make it open source, if you are interested please contact me at pabu@itu.dk
I am currently developing an action-adventure game which requires automated camera. It seems that you are currently working on this problem as a student project.
I would be very interested in knowing more about your project and if your solution could suit my needs for my current game.