Assignment of float is incorrectly set to zero.

I am have an issue with a camera set up of mine thats designed to prevent the camera from penetrating blocks, in C#. It does this by raycasting to the four points of the near clipping plane of the camera. If one of these raycasts hit, it moves the camera inward. I have managed to trace the problem down to the incorrect assignment of a float.

	public Vector3 cameraOffset = new Vector3();
	public GameObject viewCamera;
	public float clipSize = .4f;
	public float sensitivity = 15F;
	public float minimum = -60F;
	public float maximum = 60F;
	float rotationY = 0F;


	void FixedUpdate ()
	{

		rotationY += Input.GetAxis("Mouse Y") * sensitivity;
		rotationY = Mathf.Clamp(rotationY, minimum, maximum);
		transform.localEulerAngles = new Vector3(-rotationY, transform.localEulerAngles.y, 0);
		

		Vector3 realDir = transform.TransformDirection(cameraOffset);
		Vector3 hClipOffset = transform.TransformDirection(new Vector3(clipSize, 0f, 0f)); // Setup Raycasts
		Vector3 vClipOffset = transform.TransformDirection(new Vector3(0f, clipSize/2f, 0f));
		
		
		RaycastHit urHit; // Raycast info holders
		RaycastHit ulHit;
		RaycastHit lrHit;
		RaycastHit llHit;
		float modifyDist = 1f;
		
		Vector3 urDir = realDir + vClipOffset + hClipOffset; // Specify the directions to the four corners of the cameras near clipping plane
		Vector3 ulDir = realDir + vClipOffset - hClipOffset;
		Vector3 lrDir = realDir - vClipOffset + hClipOffset;
		Vector3 llDir = realDir - vClipOffset - hClipOffset;
		if (Physics.Raycast(transform.position, urDir, out urHit, urDir.magnitude)) { // check if it clips upper right edge
			float a = urHit.distance / urDir.magnitude; //prevent penetration by pushing camera in
			if (a < modifyDist) modifyDist = a;// always use the closest collision
		}
		if (Physics.Raycast(transform.position, ulDir, out ulHit, ulDir.magnitude)) { // check if it clips upper left edge
			float a = ulHit.distance / ulDir.magnitude; //prevent penetration by pushing camera in
			if (a < modifyDist) modifyDist = a;// always use the closest collision
		}
		if (Physics.Raycast(transform.position, lrDir, out lrHit, lrDir.magnitude)) { // check if it clips lower right edge
			float a = lrHit.distance / lrDir.magnitude; //prevent penetration by pushing camera in
			if (a < modifyDist) modifyDist = a;// always use the closest collision
		}
		if (Physics.Raycast(transform.position, llDir, out llHit, llDir.magnitude)) { // check if it clips lower left edge	
			float a = llHit.distance / llDir.magnitude; //prevent penetration by pushing camera in
			if (a < modifyDist) modifyDist = a;// always use the closest collision
		}
		
		Debug.DrawRay(transform.position, urDir, Color.green); // ur debug draw rays
		Debug.DrawRay(transform.position, ulDir, Color.red); // ul
		Debug.DrawRay(transform.position, lrDir, Color.cyan); // lr
		Debug.DrawRay(transform.position, llDir, Color.yellow); // ll
		
		
		
		viewCamera.transform.localPosition = cameraOffset * modifyDist; // modify the normal vector
		
			
		
		viewCamera.transform.LookAt(transform.position); // always look at this transform
	}

Using Debug code not shown here, i have traced the problem to this section of code.

    			float a = llHit.distance / llDir.magnitude;
    			if (a < modifyDist) modifyDist = a;

The value modifyDist seems to get assigned to 0 (modifyDist is a float), even thought the value of a is not zero. This is the only code in the script, so the problem must occur here.

The issue only happens on the two left side raycasts, with the right side working properly. The only difference between the two sides is the hClipOffset beings subtracted instead of added.

The small section of code right above returns valid numbers, but the assignation fails, for example this was debug logged directly after the if statement:
llHit.distance = 7.5116
llDir.magnitude = 10.15666
a = .73263
modifyDist = 0

I have no idea why modifyDist is being set equal to zero, or why it is only happening on the left side. Any help will be appreciated.

ok, but what is your question?

Why is modifyDist registering as 0?

Ok, if it is zero, is because something assigned it. What is the exactly value of "a" (100 or 0.0000001) when this happens? What is the type of modifyDist?

modifyDist is a private float and until i started debugging it never left the scope of this method (this is all in a fixed update in a script, and is the only code in it). I have debugged logged "a" right before the assignment happens, and a decimal like .75321 is typical.

So here's one problem: if (Physics.Raycast(transform.position, ulDir, out ulHit, ulDir.magnitude)) { // check if it clips upper left edge float a = urHit.distance / ulDir.magnitude; //prevent penetration by pushing camera in if (a < modifyDist) modifyDist = a;// always use the closest collision } This is inconsistent, you are setting a to a combination of things from ur and ul.

2 Answers

2

Line 16, urHit instead of ulHit. The line 15 raycast is (correctly) using UL in ulDir and output ulHit, but line 16 incorrectly uses uRhit (R instead of L) to compute A.

In general, whenever you cut&paste you need to be extra careful about these things. Sometimes setting up a size-4 array with a loop instead of cut-paste can be less error-prone (less code to check, and mistakes will fail big.)

You’re debugging even showed it – fails on Left with no Right. Just a few more Debugs would have gotten you there. But it’s hard to force yourself to reread your own code slowly and see what’s exactly there. Like how you never see “the the” in our own writing.

Thank you, Owen and Bunney83, for your help. It was stumping me and i had only about 10 more minutes before i had to leave, so i quickly threw the question up here which lead to some problems with the readability of my code. Thanks for suffering through it. The loop was up next on my list of optimizations, but i got distracted by this problem.

Ok stick with me, I am not sure this is your issue, but I have had a similar problem. Did you at any point have modifyDist explicitly set to public and set to zero? The issue I once had is that I had a public float that I started off at one value, then when I changed it via code it did not actually change because it was reading the value from the inspector which was not what I wanted. So I fixed it by explicitly setting my float to private.

If this does not help all you can really do is keep Debug Logging the crap out of your code and it will eventually make sense :slight_smile:

Good luck!

The modifyDist variable is not public and does not leave the scope of this function. Anything that can edit it is in the posted code.

Oh my, thanks for pointing that out, i seem to have chopped off some of my variables. I will update the original code to include the rest of them.