Z Rotation Not Working

I’m using Instantiate in my block breaker game to drop leaves from a tree when the ball hits it. I have a Serialized Field on my Tree script and I’ve placed my Leaf prefab in there in the editor. When I hit the tree with the ball it spawns leaves, which then slowly drop to the ground. Jackpot.

However, within my Leaf prefab, I have a Leaf script that is supposed to be rotating the leaf on the Z-axis to simulate the leaf gently floating down (it’d probably be better to use the actual particle system to do that, but I’m giving it a shot based just on what I’ve learned from the tutorials so far). When I look at my prefab the Z-axis rotation of the leaf is at 0.

In my Leaf.cs I’m declaring an enum to keep track of if the leaf is currently rotating left or right, I set the speed, and declare some extra variables:

enum FloatDirection {
	Left = 1,
	Right = 2
}

[SerializeField] float RotateSpeed = 0.4f;

float LowRotationRange;
float HighRotationRange;
float CurrentRotation;
FloatDirection CurrentDirection;

Then in my Start method, I’m randomly generating how far to the left and right the leaves can rotate (so they don’t all look identical):

HighRotationRange = UnityEngine.Random.Range(100f, 250f);
LowRotationRange = HighRotationRange * -1;

And randomly generate somewhere in that range for the rotation to start (so they don’t all start in exactly the same spot):

CurrentRotation = UnityEngine.Random.Range(LowRotationRange, HighRotationRange);

I randomly decide if it’s starting going left or right:

if (UnityEngine.Random.Range(1, 2) == 1) {
	CurrentDirection = FloatDirection.Left;
} else {
	CurrentDirection = FloatDirection.Right;
}

And then I set the rotation to my newly generated value:

transform.rotation = new Quaternion(0, 0, CurrentRotation, 0);

So my full Start method looks like this:

void Start() {
	HighRotationRange = UnityEngine.Random.Range(100f, 250f);
	LowRotationRange = HighRotationRange * -1;
	CurrentRotation = UnityEngine.Random.Range(LowRotationRange, HighRotationRange);
	if (UnityEngine.Random.Range(1, 2) == 1) {
		CurrentDirection = FloatDirection.Left;
	} else {
		CurrentDirection = FloatDirection.Right;
	}
	transform.rotation = new Quaternion(0, 0, CurrentRotation, 0);
}

For my Update method, I check if the direction of the leaf needs to change, I figure out what the new rotation should be, and I set that new rotation:

void Update() {
	CheckIfDirectionNeedsToChange();
	AdjustRotation();
	ApplyRotation();
}

Within CheckIfDirectionNeedsToChange I see if it’s floating to the left and has passed the minimum rotation value or if it’s floating to the right and has passed the maximum rotation value; if either of those are true I change the direction:

private void CheckIfDirectionNeedsToChange() {
	if (CurrentDirection == FloatDirection.Left && CurrentRotation < LowRotationRange) {
		CurrentDirection = FloatDirection.Right;
	} else if (CurrentDirection == FloatDirection.Right && CurrentRotation > HighRotationRange) {
		CurrentDirection = FloatDirection.Left;
	}
}

Within AdjustRotation I either add (if it’s floating right) or subtract (if it’s floating left) the RotateSpeed value to get an updated CurrentRotation value:

private void AdjustRotation() {
	if (CurrentDirection == FloatDirection.Left) {
		CurrentRotation -= RotateSpeed;
	} else {
		CurrentRotation += RotateSpeed;
	}
}

Lastly, in ApplyRotation I update the rotation of the transform and print out the value to the Debug log so I can see if it’s working:

private void ApplyRotation() {
	Debug.Log($"Changing Z rotation to {CurrentRotation}");
	transform.rotation = new Quaternion(0, 0, CurrentRotation, 0);
}

The issue I’m having is that my Debug log gives me updated values every frame that go from the minimum value to the maximum value and back again, but it doesn’t actually rotate my GameObject, which seems like it should be fine (and in fact works fine in other parts of my game when I want to flip a sprite from facing left to facing right, though there I’m rotating on the Y-axis). Even odder, if I pause the game after the leaf is Instantiated and click on it in the editor its Z rotation is always set to -180.

Any idea what I might have done wrong here? The logic seems right in my brain, and the Debug log seems to confirm that, but yet no rotation is actually happening.

Thanks in advance for any fixes/ideas.

Hi,

What value range does CurrentRotation have?

Quaternions are not Euler angles. Maybe you could test Quaternion.Euler instead of calling the Quaternion constructor in the ApplyRotation method.

The value of CurrentRotation would be constantly changing; the idea was it would cycle back and forth between -100 and 100 (which is higher than I’d actually want it, but I initially wasn’t sure if my rotation amount was too small so I just didn’t notice that it was actually working).

I can definitely give Quaternion.Euler a try, but I’m not sure how exactly I would use that based on the examples in your link. For instance, in this example:

Quaternion rotation = Quaternion.Euler(0, 30, 0);

I can definitely put code like that in my CS file, but I’m not sure what to do with that rotation variable then. Does that, by itself, rotate the object? Or do I need to put it inside something like transform.Rotate() like with the new Quaternion() in my code (currently at work so I can’t just plug it into my code to try it out at the moment)?

I can definitely put code like that in my CS file, but I’m not sure what to do with that rotation variable then.

I’m not telling you the solution because I believe that you are almost there. Here’s a hint:

The transform.rotation property expects an object of type Quaternion or null. Quaternion.Euler returns an object ot type Quaternion.

If that’s not clear, here is another hint:

HighRotationRange is a variable of type float. Random.Range returns a float.

If that didn’t help either, here’s the solution:

Quaternion rotation = Quaternion.Euler(0, 30, 0);
transform.rotation = rotation;

// Alternatively:
transform.rotation = Quaternion.Euler(0, 30, 0);
1 Like

Awesome, thanks so much for the help, and thanks for putting the solution in spoiler tags so I could figure it out partially on my own. I’ve been programming a long time but it’s been a while since I learned something really new so I’ve gotten out of the habit of “go look at the documentation.” I need to work on that.

I had originally tried using the Quaternion you had recommended in transform.Rotate (something I kept seeing others online talk about), but it didn’t like that, and for some reason I didn’t think to go back to the transform.rotation property.

Thanks again for the help!

You’re welcome. :slight_smile:

Do you happen to have an idea of why the following bits of code work for changing my sprite from facing left to facing right (and vice versa)?

transform.rotation = new Quaternion(0, 180, 0, 0);
transform.rotation = new Quaternion(0, 0, 0, 0);

The fact that this was working for me at a different point when I needed to rotate on the Y-axis is why I was trying to use similar code to rotate on the Z-axis. Should I be switching that Y-axis rotation code to be the same as what you recommended here?

Before I can answer any of your questions regarding your example code, I’d like to know what you think 180 is. A degree value? And where would you put your variable in the Quaternion constructor?

Yes, I would assume 180 is a degree, and I’d put it in the constructor for whichever axis I wanted to rotate 180 degrees, like I did above. In the original example I was putting it in the position for the Z-axis, in the followup question I was putting it in the position for the Y-axis, and it seemed to work in one of those cases but not the other.

Also, I’m not going to pretend for even a second that 90+% of those videos made any sense to me.

In that case, use the Euler method because the second parameter of the Quaternion constructor is not a degree value. The last three parameters form a Vector. The first one a scalar that stores the rotation around the vector.

https://scriptinghelpers.org/blog/how-to-think-about-quaternions

Use the Euler method, got it! :slight_smile:

I appreciate all the help on this (and the few other topics you’ve helped me on). I’ll keep digging into Quaternions and see if I can find an explanation that doesn’t make my brain hurt (that last link of yours was a bit better for me, I felt like I got a little further into it before I got completely lost).

You’re welcome. :slight_smile:

Regarding the quaternions, it’s interesting that you found the article easier to understand because I preferred the numberphile video. There are more explanations on the internet. I’m sure you’ll find one which will help you understand thus subject.

Have a nice weekend!

You have an error when you get random rotation direction.
UnityEngine.Random.Range(1, 2) == 1 will always give 1.
you should use it like UnityEngine.Random.Range(0, 2) == 0

1 Like

Nice catch, thanks! I thought it was (inclusive, exclusive) but when I looked at the tool tip as I typed it it said (inclusive, inclusive); turns out that’s just for floats whereas I’m using ints. Odd that they’re different.

Anyway, appreciate the help.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms