- Home /
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, 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.
Answer by Owen-Reynolds · Apr 29, 2013 at 08:42 PM
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 $$anonymous$$utes 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.
Answer by justin_iSO · Apr 29, 2013 at 02:25 PM
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 :)
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.
Where and how do you calculate "realDir" "vClipOffset" "hClipOffset" ? You seem to calculate a "normalized" distance, but i don't get why...
It's also a bit confusing. This script doesn't seems to be attached to the camera, so you have another gameobject, probably a child of the camera. Where is that object located and how do you actually use the modifyDist variable at the end.
From what you've provided here no one can solve your problem, there are way to many "unknown variables". Like justin said, start debugging by using Debug.DrawLine and Debug.Log. Wherever you do calculations make sure the result (even temp results) are within the expected range.
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.
Your answer
Follow this Question
Related Questions
How can i change a variable on the object hit by a raycast C# 2 Answers
wheel script raycast 1 Answer
zero is not zero 2 Answers
Raycast - Input position is Infinity | Point Precision 1 Answer