Physics and quaternions not playing well together

Hello, I was hoping I could get a little insight about properly setting an object’s rotation with a script. The only thing I can find is by using Quaternions. My object turns 40 degrees then the right key is press, -40 degrees when the left key is pressed, and 0 when both are pressed.

But I get a problem when my object, a rigidbody2D, bumps into a wall. It acts as it should by colliding and changing the rotation due to external forces. But this throws off my objects axis or something. The object no longer rotates to the absolute angle I have specified but instead the rotation now seems relative to the offset from physics rotation.

I used the debugger to check the quaternion values and they are as they should. The only thing that is off is the transform.rotation of the object. How can I more directly influence tranform.rotation rather than using quaternions? Any suggestion or information would be very greatly appreciated.

Please show the code you wrote to get your results.

If you’re doing 2d physics, you most likely won’t need quats since they’re more for 3d rotation.

What should I use instead? I can’t access transform.rotation and modify it directly with C#. That only works with Javascript which is depricated in Unity now, right?

Last time I did 2D was on flash back in early 2000’s but as far as I remember 2D rotation is just the angle, be it a number from -180 to 180, 0-360 or some from of Pie or Tau.

What do you mean you can’t access transform.rotation with C#?
“Javascript” has been outdated for years now(on unity) and is infact completely removed in 2018+.

Show us the code you’re using.

To rotate a 2D object in Unity, its just like any other 3D object. ALL objects in unity us the exact same transform component. If it is in 2D, i only need to worry about the Z axis.

I can’t use “transform.rotation.z”. This was never possible with Unity C#, only Javascript for some reason. The console says “Cannot modify a value type return value of ‘UnityEngine.Transorm.rotation’. Consider storing the value in a temporary variable.”

This is why I was using Quaternions. It seems to be the only way to specify a rotation with a script and that looks something like this: transform.rotation = Quaternion.Euler(0, 40, 0);

My script is a little more complicated than that. I am using Quaternion.Lerp so the object transitions between the target angles. But Lerp isn’t the problem. Setting a specific angle with Quaternion.Euler has the same problem.

While typing this message, I found a solution. I can set my angles with transform.eulerAngles instead and I get the desired result.

In conclusion for anyone struggling with scripting angles, Quaternions are terrible. Stay away from them. transfrom.eulerAngles are the way to go.

So… did you try storing the value in a temporary variable?

Quaternion rot = transform.rotation;
//do stuff to rot
transform.rotation = rot;

Quaternions are good, but they are unintuitive AF and that makes it hard to work with them(for us common folks), but you have a bunch of function that helps you out, the euler angles you’re using are translated from and to a quaternion.
https://docs.unity3d.com/ScriptReference/Quaternion.html

Storing the value to a temporary value won’t allow me to change it.

As for Quaternions, I know they don’t suck. It’s like you said. Not intuitive.

As for the problem with the angular offset from external physical forces, well now the offset is forcing the object to continually rotate. My problem isn’t solved after all. :frowning:

Here’s the code
void PlayerLateral()
{
if (Input.GetButton(“Right”) && Input.GetButton(“Left”))
{
transform.eulerAngles = new Vector3(0, 0, NewAngle);
if (NewAngle != 0.0f)
{
if (NewAngle > 0.01f)
{
NewAngle -= 50.0f * Time.deltaTime;
}
if (NewAngle < 0.01f)
{
NewAngle += 50.0f * Time.deltaTime;
}
else if (NewAngle <= 0.01f && NewAngle >= -0.01f)
{
NewAngle = 0.0f;
}
}

isThrusting = true;
}
else if (Input.GetButton(“Right”))
{
transform.eulerAngles = new Vector3(0, 0, NewAngle);
if (NewAngle > -40.0f)
{
NewAngle -= 100.0f * Time.deltaTime;
}
if (speed < 4.0f)
{
speed += 100.0f * Time.deltaTime;
}
GetComponent().AddForce(new Vector2(speed, 0));
isThrusting = true;
}
else if (Input.GetButton(“Left”))
{
transform.eulerAngles = new Vector3(0, 0, NewAngle);
if (NewAngle < 40.0f)
{
NewAngle += 100.0f * Time.deltaTime;
}

if (speed > -4.0f)
{
speed -= 100.0f * Time.deltaTime;
}
GetComponent().AddForce(new Vector2(speed, 0));
isThrusting = true;
}
else
{
isThrusting = false;
NewAngle = transform.rotation.z;
}
}

Oh. It seems my last post is invisible until a moderator reads it. I was explaining my problem hasn’t gone away and I tried to show my code. Hopefully you’ll see it soon.

https://discussions.unity.com/t/481379

What do you mean by that?

Use code tags:

I meant to say “Storing the value to a temporary variable won’t allow me to change it.” My bad. Hope that clears it up. If I’m wrong about my statement, please let me know as I am not a programmer. I’m just and artist who is trying his best. LOL

Thanks for showing me that!

After working over the code last night, I finally understand my original issue. I am setting the rotation with code, and the collision was creating an offset with different results when set with quaternions or with transform.eulerAngles which is why it was difficult for me to understand what was going on. But what’s happening is that the ridgidbody was getting force applied to it causing it to rotate. The ridgidbody had no angular drag so that force never rested.

If you want a clue of what I was trying to accomplish, look at the gif I attached.

I’m gonna finish this up and learn how to properly write forum posts. XD4142056--364621--Prototype.gif

That’s pretty much the same sentence, I meant what’s the problem doing it like I showed you before

There is no problem. Your way is much more succinct than mine. I’ll be sure to remember it! My apologies. I’m not intuitive at programming so I didn’t see how it would have helped. I didn’t see how it was much different from transform.rotation.x = 0.0f or something like that which doesn’t work. I tried it your way and it works. It’s actually similar to many ways I’ve tried and scrapped because it didn’t solve my original problem.

I want influence the rotation of this rigidbody while allowing it to be effected by physics. I may rebuild the game object with a limited hinge joint and motors or something.

Beware using Quaternions like this. The x component of a quaternion does not correspond to a rotation around the x-axis. You can use transform.rotation = Quaternion.Euler(x,y,z);, or access the transform’s eulerAngles directly with transform.eulerAngles = new Vector3(x,y,z);. There are more advanced usages for Quaternion that you might need later, but just be aware that modifying the x component of a Quaternion does not generally cause a rotation in the way you might be expecting. Unity - Scripting API: Quaternion

Since you want to influence the rotation of the game object while still allowing it to be affected by physics, you’ll likely want to use Rigidbody.rotation instead of Transform.rotation: Unity - Scripting API: Rigidbody.rotation

Oh wow! Thank you for the insight!
I’m trying the Rigidbody.rotation instead but I’m still getting the same results but the rotation is noticeably smoother. I’m sure there is more to this. I will keep reading and experimenting.

So far, I have used
1.Quaternions: I get the target angle I want but can be offset by rigidbody forces, specifically collision that causes torque.
2.transform.eulerAngles: Target angle achieved but doesn’t account for rigidbody torque when statement is no longer called.
3.GetComponent().rotation: I get the target angle but transition is much smoother as it runs in physics. Torque still applied when statement is no longer called.

I suppose the original problem is much less a mystery. I’m changing the rotation more effectively with everyones’ help. Thank you. And because of that, I see that I’m treating transform and rigidbody forces like they are the same thing when they aren’t. What I learned is that moving an object with transform does not give it force.

I feel so silly for not seeing this sooner. I should stick to art and leave the programming to the programmers. LOL

-----------------SOLVED------------------

WOOOHOOO!!! I got it working perfectly now completely bug free!
GetComponent().rotation is the way to go to influence the rotation of a rigidbody.

Thanks so much WallaceT_MFM!

Here is the result:
4144123--364954--Prototype602.gif