- Home /
Why comparing float values is such difficult?
Hi,
I am newbie in Unity platform. I have 2D game that contains 10 boxes vertically following each other in chain. When a box goes off screen, I change its position to above of the box at the top. So the chain turns infinitely, like repeating Parallax Scrolling Background.
But I check if a box goes off screen by comparing its position with a specified float value. I am sharing my code below.
void Update () {
offSet = currentSquareLine.transform.position;
currentSquareLine.transform.position = new Vector2 (0f, -2f) + offSet;
Vector2 vectorOne = currentSquareLine.transform.position;
Vector2 vectorTwo = new Vector2 (0f, -54f);
if(vectorOne.y < vectorTwo.y) {
string name = currentSquareLine.name;
int squareLineNumber = int.Parse(name.Substring (11)) ;
if(squareLineNumber < 10) {
squareLineNumber++;
} else {
squareLineNumber = 1;
}
GameObject squareLineAbove = GameObject.Find ("Square_Line" + squareLineNumber);
offSet = (Vector2) squareLineAbove.transform.position + new Vector2(0f, 1.1f);
currentSquareLine.transform.position = offSet;
}
}
As you can see, when I compare vectorOne.y and vectorTwo.y, things get ugly. Some boxes lengthen and some boxes shorten the distance between each other even I give the exact vector values in the code above.
I've searched for a solution for a week, and tried lots of codes like Mathf.Approximate, Mathf.Round, but none of them managed to compare float values properly. If unity never compares float values in the way I expect, I think I need to change my way.
I am waiting for your godlike advices, thanks!
EDIT
The comments state that I need to use an array, I used array in the code below but I still need GameObject.Find functions because how can I find the objects to change their positions in another way?
Vector2 vectorTwo = new Vector2 (0f, -55f);
for (int i=1; i<11; i++) {
GameObject squareLine = GameObject.Find("Square_Line" + i);
if(squareLine.transform.position.y < vectorTwo.y) {
GameObject squareLineBelow = null;
if(i == 10) {
squareLineBelow = GameObject.Find("Square_Line1");
} else {
squareLineBelow = GameObject.Find("Square_Line" + (i+1));
}
squareLine.transform.position = (Vector2) squareLineBelow.transform.position + new Vector2(0f, 11f);
} else {
squareLine.transform.position = (Vector2) squareLine.transform.position + new Vector2(0f, -0.1f);
}
}
This code block remains in Update() function. This works fine but If you think it is not a good approach for performance, please warn me. Thanks.
That's not a proper way of doing it. You should add the box on the top not at a fixed position but at a position relevant to the box below it. Update() doesn't work at fixed intervals. Hence, you find distance between the boxes. Use an array ins$$anonymous$$d for the boxes so that you don't have to exhausting functions like GameObject.Find, Parsing and substring.
1 note about the code
offSet = (Vector2) squareLineAbove.transform.position + new Vector2(0f, 1.1f);
offSet = begginningPosition;
Those 2 lines are competing with eachother. Former line is actually overriden by latter. Did you mean offSet += begginningPosition; ?
Answer by sumeeton · Apr 01, 2015 at 08:10 PM
As I mentioned earlier the problem is not with comparing float values. I'll explain it to you stepwise.
First use array of gameobjects as public field:
public GameObject[] box;
Now when you have attached the script to a gameobject say a GameManager, you can see in the inspector that you can set the number of GameObjects for box. Set it to 10. Then drag and drop the 10 different squares for each slot in the inspector for box field.
Once you have done that, you now have references to all your boxes in the box array.
Now we need to set boundaries for the box to disappear whenever the box crosses it's limits. Since, we are worried about vertical scrolling in downward direction only, we'll use a float for this.
float boundary = -5.0f; // Set the values as per your requirement
Once we have this, we'll need fixed distance between two boxes.
float boxDistance = 0.2f; // Set this to the distance you want between two boxes
Now, you'll have to move these boxes in the Update(). I'm assuming that you're moving them vertically downwards. So, I'll only post the code to move the box at the top.
void Update ()
{
// move the boxes and do whatever you want to
// if the box moves out of the boundary, place it at the top position
// the following logic assumes that only one can move out of the boundary in a single Update
for (int i = 0; i < box.length; i++)
{
if(box[i].transform.position.y < boundary)
{
// Get the box index at the top
int topIndex = (i+1) % box.length;
// Place the current box at the top separated by the distance (note: x & z aren't changing)
box[i].transform.position = new Vector3(box[i].x, box[topIndex].y + boxDistance, box[i].z);
break;
}
}
}
Now, it's fixed. You can now change the code as per your requirements. Also, this is more flexible now. You can add as many boxes you want through the inspector. Make boundary and distance public, and you'll be able to set them too.
Following image explains the trick:
Thank you. I attached the script to $$anonymous$$ainCamera. It works with a better performance than $$anonymous$$e.
Your answer
![](https://koobas.hobune.stream/wayback/20220613191820im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
How to compare float for equality? 2 Answers
if get key and float bigger as 1 Answer
Unity 2*10^-16 == 0 is true!! 1 Answer