Raycast not detecting collision

Hi there,

I have created a custom script that was supposed to control the 3rd person camera in a TPP game. Alas, the raycast that I use to check if the camera’s line of sight is blocked by anything doesn’t work. Here is the code:

        public Transform playerCam;
	public Transform camLooker;
	public Vector3 camVector;
	
	// Use this for initialization
	void Start () 
	{
		playerCam = GameObject.Find("Main Camera").transform;
		camLooker = transform.Find("CameraLooker");
	}
	
	// Update is called once per frame
	void Update () 
	{
		float camDistance = Vector3.Distance( camLooker.transform.position, playerCam.position );
		camLooker.transform.LookAt(playerCam);
		camVector = camLooker.transform.TransformDirection(Vector3.forward);
		RaycastHit hit;
		Physics.Raycast(camLooker.transform.position, camVector, out hit, camDistance, ~1<<9);
		if (hit.collider)
		{
			playerCam.transform.position = hit.point;
			playerCam.transform.LookAt(camLooker);
		}
		
	}

Layer 9 is the player, as the raycast originiates in the center of the player, is shot outwards towards the camera and detects if anything is in the way (at least, that is the intended behaviour). camLooker is an empty gameobject that points to the direction of the camera.

The camera is a child of the Player, maybe that is the fault here? Any help appreciated

In what way doesn’t it work? Doesn’t detect objects in it’s path? Detects objects that aren’t in its path?

Seems fine to though. You could try reversing the ray to go from camera to player and see what that does.

I did that, but even if it worked (which it didn’t) I would still require the RaycastHit to be the point closer to the player, rather than closer to the camera (if I cast the ray from the player, the ray should return the first point it encounters, allowing me to safelly position the camera so that no obstruction is in the way)

As it is now, RaycastHit.collider returns Null all the time, be it a BoxCollider or MeshCollider it is supposed to hit.I checked that the ray is cast in the correct direction via Debug.DrawRay.

One thing though – not sure about layers. Does the ray keep on searching for a hit if it passes through a layer it is supposed to ignore? or does it stop there and return Null? If that is the case, then I know where to go from there more or less.

I’m fairly sure the ray does continue after hitting a layer it should ignore. I had a problem with the ray hitting the inside of the object casting the ray, but adding the object to an ‘ignoreLayer’ solved that.

The only other thing I can think of is the distance. Does it actually reach all the way to the camera’s collider?

Tobias is right, the ray will ignore layers that you specify. You may want to enable draw the ray so that you can see what’s going on, I think it was Debug.DrawRay or something like that…

I got it working somewhat, thanks for the tips!

No idea what fixed it though – I revised and revised untill it worked. And now, a different bug showed its ugly head.

Below is the code:

using UnityEngine;
using System.Collections;

public class ThirdPersonCamera2 : MonoBehaviour {

	public Transform playerCam;
	public Transform camLooker;
	public Vector3 camVector, camOrigin, camOriginRot;
	float camMaxDist;
	bool isChanged=false;
	RaycastHit hit;
	int layerMask;
	
	// Use this for initialization
	void Start () 
	{
		playerCam = GameObject.Find("Main Camera").transform;
		camLooker = transform.Find("CameraLooker");
		camMaxDist = Mathf.Abs( Vector3.Distance( playerCam.position, camLooker.position ) );
		layerMask = 1 << 9;
		layerMask =~layerMask;
		camOrigin = playerCam.localPosition;
		camOriginRot = playerCam.localEulerAngles;
		
	}
	
	// Update is called once per frame
	void Update () 
	{
		
		camMaxDist = Mathf.Abs( Vector3.Distance( playerCam.position, camLooker.position ) );
		camLooker.transform.LookAt(playerCam);
		camVector = camLooker.transform.TransformDirection(Vector3.forward);
		Physics.Raycast(camLooker.transform.position, camVector, out hit, camMaxDist, layerMask);
		if (hit.collider)
		{
			if ( isChanged == false ) 
			{
				isChanged = true;
				
			}
			playerCam.transform.position = hit.point;
			playerCam.transform.LookAt(camLooker);
			Debug.DrawLine(camLooker.transform.position, hit.point);
			
			
		}
		Debug.Log (hit.collider);
		
		if ( ( isChanged == true )  ( !hit.collider ) )
		{
			playerCam.localPosition = camOrigin;
			playerCam.localEulerAngles = camOriginRot;
		}
	
	}
}

The code works so that when there is no collider between the camera and the player (looking from the player’s perspective) the camera defaults back to it’s original location. Problem is, it seems that the raycast isn’t done each frame/does not return true each frame. Under certain angles there seems to be a collision one frame, and no collision the other. The Debug.Log literally spits out Null and the colliding object as it sees fit. Is there some limitation to the Raycast function?

The most disturbing part is that when the angle is right, it returns a constant stream of collisions, while moving a mouse just a bit (thus rotating the whole thing) makes the camera go back and forth. Could it be that it is still colliding with the CharacterController all the time? I made sure that the object is in the ignored layer, and set the mask according to the reference guide.

EDIT: I just went with a hunch, and yes, the problem is how far the raycast is actually cast. The jitter happens when the ray barelly touches the surface, and it seems the engine calculates differently for each frame (quite a bummer). Seems I’ll just have to make sure there is a buffer in the ray lenght.

EDIT: Feel free to laugh at my obvious mistake here ^^‘’ The distance of the ray was needlesly calculated each frame, and it changed for no good reason. All works fine and dandy now.