IsStanding code, take 2

Like others, I also had some odd issues with the IsStanding code. Part of it is that I’m using garden gnomes (which has been a hassle), and they had slightly different rotations. While noticing that angles were never 0, I found this nice little function:

    MathF.DeltaAngle(angle1, angle2).

DeltaAngle returns the difference between two angles. It takes care of negatives, wrap around 360, etc. So, I just used 0 as the angle to compare against (the original code could use 270 I guess). So, with my gnomes (different model) here’s the code:

	public bool IsStanding () {
	Vector3 rotationInEuler = transform.rotation.eulerAngles;

	//jdg: note this is called every tick
	float tiltInX = Mathf.DeltaAngle(rotationInEuler.x,0);
	float tiltInZ = Mathf.DeltaAngle(rotationInEuler.z,0);

	if ((tiltInX < standingThreshold) && (tiltInZ < standingThreshold))
	{
		return true;
	}
	else
	{
		return false;
	}
}

== John ==

3 Likes

Another approach you can take is checking the value of transform.up.y. An object that is standing perfectly upright will have a value of 1, and an object laying on its side will have a value of 0.

The downside to this, at least for me, is that it the value doesn’t linearly scale with angle. An object tilted by 45 degrees has a value of .65, not .5. So even though I have my threshold set at .9, I don’t actually know how much of a tilt that is >_>

I believe this code can be broken by weird rotation values: Mathf.DeltaAngle(-610,0) will return -70, for example. -70 is smaller than standingThreshold. So it would return true, if both angles were actually being rotated by -610 degrees. Maybe this would never actually happen, but since we’re learning, i tried to come up with a slight modification, which might be more robust:

  1. Use Mathf.Abs to only deal with positive delta angles.

  2. “Look” if anything is bigger than standingThreshold.

     public bool IsStanding () {
             float tiltInX = Mathf.Abs (Mathf.DeltaAngle (transform.eulerAngles.x, 0)); // Absolute (positive) delta  between transform rotation in degrees and 0.
             float tiltInZ = Mathf.Abs (Mathf.DeltaAngle (transform.eulerAngles.z, 0));
    
         if (tiltInX >= standingThreshold  || tiltInZ >= standingThreshold) {
             return false;
         }
         else {
             return true; 
         }

VIsn’t part of the problem that an Abs on an angle of -1 actually comes out as 359, and therefore would not be less than 3?

If the abs angle is >= 180 you probably need to subtract 360 and then take the abs again.

That would then correctly give you 1 degree, not 359.

In the video, Ben takes an example of 350, which is equal to a tilt of 10 and therefore over the threshold but it’s actually using the value of 350 there. This is where 359 as an example won’t work with the current code

Maybe there’s another function to do that in Unity but I’ve not read that far. Ah ok Is that what DeltaAngle is doing above?

Calculates the shortest difference between two given angles given in degrees.

See here
https://answers.unity.com/questions/554743/how-to-calculate-transformlocaleuleranglesx-as-neg.html

If you want to get the negative values for the left side, simply do the following calculations:

float angle = transform.localEulerAngles.x;
angle = (angle > 180) ? angle - 360 : angle;

You could then take the Abs, but it looks like DeltaAngle above is a neater solution

Thanks man… for now it’s been working for me.
Did you finish the game? Did it keep on working afterwards?
Cheers!

Also, take a look at this thread:

The suggested code was approved by Ben as a solution.
It is working fine on my project.

that worked great! thanks!

Thanks for the post eovento. Your solution is working!

I had this code working until Ben modified the pins to no longer have child game objects, 218 detecting pins have settled. I modified your code to have the && instead of ||

Vector3 eulerwithouttwist = Vector3.Scale(transform.rotation.eulerAngles, new Vector3(1, 0, 1));
Quaternion rotationwithouttwist = Quaternion.Euler((eulerwithouttwist));
float tiltangle = Quaternion.Angle(rotationwithouttwist, Quaternion.identity);
return (tiltangle < standingThreshold);

Privacy & Terms