1

I have a script which triggers a movement when a rotation is completed. The script casts the Euler angle of a transform to an int. If it is true, the condition is executed. For some weird reason, the code in the if condition does not execute, even if the condition is true. I have confirmed the condition is true through both my compiler and the debug log.


Here is my code:

if(rotationInitiate)
{
    transform.eulerAngles = Vector3.Slerp(transform.eulerAngles, 
        new Vector3(0, 0, angleOfRotation), Time.deltaTime * speedOfRotation);

    Debug.Log(transform.eulerAngles.z);

    if((int)transform.eulerAngles.z == 180)
    {
        Debug.Log("Hurray we have successfully executed the if statement");

        // More rotation stuff
    }
}

As you can see by my log, the angle returns an exact value of 180, but does not enter the if statement to perform the second log output:

The console prints a <code>z</code> angle of 180 degrees, but does not print the statement in the <code>if</code> statement that directly follows.


Why might my if statement not be executing?

Gnemlock
  • 5,263
  • 5
  • 28
  • 58
Ikun
  • 163
  • 8
  • Try removing that int cast – Bálint Jan 29 '17 at 09:26
  • 2
    What if you try a more robust condition like Mathf.Abs(transform.eulerAngles.z -180.f) < 1.0f? Also make sure the debug output is something unique so that it is not mistaken for some other, forgotten somewhere else, debug output. – wondra Jan 29 '17 at 11:20
  • The angleOfRotation is 180 and the speedOfRotation is 10. – Ikun Jan 29 '17 at 11:40
  • Thanks Wondra ,your solution seems to have worked. I replaced my if condition with the one provided by you and it worked. Though it still bothers me why my original solution wouldn't work. Thanks for your help too Gnemlock – Ikun Jan 29 '17 at 11:48
  • The thing is, I copied your code into my ide, and it also worked =/ I assumed you were giving a really small value or something. That said, if your moving at 10 * Time.deltaTime, Your Update method must only be beig called approx. 10 or less times per second, as that is the only situation where you could pass a value of 1 or greater into the Slerp() method. In turn, this is the only way you could immediately reach the rotation of 180, unless you already were at the rotation of 180. – Gnemlock Jan 29 '17 at 12:38
  • Note that Slerp moves incrementally, not straight away. We give it a value between 0 and 1, pointing to the increment we want. 0 means the start position, 1 means the end position, 0.5 means the middle. – Gnemlock Jan 29 '17 at 12:39
  • I did not exactly get what you were trying to say in the last two comments Gnemlock. Could you explain in a bit more detail ? – Ikun Jan 29 '17 at 15:07
  • Change {Debug.Log(transform.eulerAngles.z);} to {Debug.Log((int)transform.eulerAngles.z);} and let's see what's the output in the console. Probably nothing exceptional will appear there, but as everyone are having a hard time with this, let's try something. – Hatoru Hansou Feb 02 '17 at 00:25

3 Answers3

2

The problem is that Debug.Log(transform.eulerAngles.z); printing 180 does not mean that z has the value 180. It means it has a floating point value very close to 180, but that could be for instance 179.999969482421875.

This means that the if((int)transform.eulerAngles.z == 180) test will not work, because casting 179.999969482421875 to int yields 179, not 180.

A possible solution is to round the value: if (Math.Round(transform.eulerAngles.z) == 180.0).

sam hocevar
  • 23,811
  • 2
  • 63
  • 95
  • 1
    I agree, but in an initial screenshot I had uploaded, I had shown that the if condition was indicated true by the debugger in mono( the one which appears on hovering over the == sign). Doesn't this mean that the condition had evaluated to true ? – Ikun Jan 30 '17 at 06:35
  • The condition has not evaluated to true, since the code inside was not executed. There may be a problem in the debugger visualiser, but you should first fix your code. – sam hocevar Jan 30 '17 at 09:35
  • Interesting, I will try this out. – Ikun Jan 30 '17 at 09:45
  • This seems to explain why the code wont work. It does work, when I try it given the reported values. – Gnemlock Feb 02 '17 at 09:24
  • @Gnemlock it may sometimes work, but that’s only by chance; the outcome will highly depend on the value of DeltaTime. – sam hocevar Feb 02 '17 at 13:54
1

I copy pasted your code into a coroutine:

private IEnumerator TestCoroutine()
{
    GameObject newGameObject = new GameObject();

    while (true)
    {
        newGameObject.transform.eulerAngles = Vector3.Slerp(
            newGameObject.transform.eulerAngles, 
            new Vector3(0, 0, 180), Time.deltaTime * 10);

        Debug.Log(newGameObject.transform.eulerAngles.z);

        if ((int)newGameObject.transform.eulerAngles.z == 180)
        {
            Debug.Log("Hurray we have successfully executed the if statement");
        }

        yield return null;
    }
}

I ran it, and it worked:

It works when I try it in a Coroutine.

Gnemlock
  • 5,263
  • 5
  • 28
  • 58
WindyKeeper
  • 149
  • 2
  • It's Unity Version 5.4.1f1 personal edition – Ikun Jan 29 '17 at 15:04
  • @Ikun, you say that this solution worked. Could you please confirm by confirming the answer? – Gnemlock Feb 02 '17 at 09:14
  • Why is this accepted if the code is still obviously wrong? – sam hocevar Feb 02 '17 at 19:17
  • I had originally accepted this answer, as it had shown that my code was right but the problem seems to be with my environment. But then I realized that even Sam's answer is right and kind of more detailed about the possible causes, to the problem. So I have decided to accept that answer. That being said I have upvoted this answer as well so it might be helpful to some people. Thank you all for the help. – Ikun Feb 03 '17 at 17:28
0

Since you are using a slerp and casting to int, your rotation doesn't actually ever hit 180, since casting cuts off anything after the comma (179.999999999999.. => 179). The Debug.Log rounds instead, so if you want the behavior to be the same try Mathf.Round instead of the int cast.

It is better to use the solution Wondra posted in the comment above though, this is just to make it clear why it broke before.

Nicki
  • 184
  • 2
  • It does. And the user demonstrated that the if statement is false if((int)transform.eulerAngles.z == 180) , as it didn't write out the Debug.Log("Hurray we have successfully executed the if statement"); but only the rounded Debug.Log(transform.eulerAngles.z); – Nicki Feb 02 '17 at 09:13
  • Huh, very strange indeed. :) Oh wait, the slerp t value doesn't seen to be advanced from step to step, wouldn't this mean that it would not "move" but rather shake around the value of Time.deltaTime? – Nicki Feb 02 '17 at 09:54
  • It should, it is clear the original asker did not initially understand how Lerp and Slerp work. It also appears strange that they would have the reported issues, regardless. I have confirmed that the code works, on my side, and another user reports something similar. – Gnemlock Feb 02 '17 at 09:56