- Home /
Unity 5.0 Physics Freeze rotation not working
I've set freeze rotation on my objects to true, but for some reason whenever they bounce off a wall or finish moving they are rotating. I just recently upgraded my project from 4.3 to 5.0. Before I updated, the physics was working fine and I never had this problem. I've changed several settings, but I can't seem to fix it.
Each of the objects is using a capsule collider, and they have rigidbodies set to interpolate and continuous dynamic with freeze rotation on for each axis.
Has anyone else run into this problem?
I'm glad I'm not the only one to have this issue. I hope they fix it soon. I'm getting very frustrated and considering using some workaround that doesn't include rigidbodies. What I REALLY wish I had was a way to push two colliders just outside of each other without having to use rigidbodies, but ID$$anonymous$$ how to do that. $$anonymous$$y game isn't particularly physics intensive. I mostly just use physics to keep two objects from occupying the same space.
Same issue here, two box colliders clipping slightly on the floor, normally it would just glide over but ins$$anonymous$$d its enough to throw my Y axis spinning. Y should be frozen.
All the physics are handled on the parent and its the parent that is spinning.
Really weird thing is I wrote a work around to constantly realign Y, but even that seems to fail and I still spin. That might be my shoddy code however...
Which update are you doing that in? Because my understanding is physics happens right after FixedUpdate, but before Update and LateUpdate. In theory if you re-align your y-axis in LateUpdate, it should work.
It's almost 2016 now. It's still happening? Any updates on the bugfix?
edit: manually re-aligning the gameObject in the LateUpdate (as mentioned by Sprite101) seems to work. It's a bit hacky, I guess, but hey, in the end it does what it does.
If you don't have an enormous amount of gameObjects that needs this fix, I would say go for it.
Answer by SergeMos · Jan 20, 2016 at 12:39 PM
I resolve the problem this way
void FixedUpdate(){ Vector3 oldRot = transform.rotation.eulerAngles; transform.rotation= Quaternion.Euler(oldRot.x, 90,oldRot.z); } (Fixed Y)
Yes, in FixedUpDate this does seem to work. Essentially the same thing, but on a rigidbody. Thanks!
Quaternion rot = Quaternion.Euler( 0, r.rotation.eulerAngles.y, 0 );
r.rotation = rot;
Answer by Danbear · Mar 15, 2015 at 02:25 AM
Janis I went ahead and got a substitute constraint script to work. My scripting issue was I was changing the transform in other places during FixedUpdate, so I had to move my changes into Update to constrain them.
It also let me set Min and Max rotations and allow for custom recovery speeds (so it turns back forward (quickly) instead of just locking down, it looks more realistic in the end).
Here is a copy of my code if it helps.
#pragma strict
private var baserot: Vector3;
var xreturnspeed: float;
var yreturnspeed: float;
var zreturnspeed: float;
var xmin : float;
var xmax : float;
function Start () {
//saves the initial rotation for use as the "home" rotation.
baserot = transform.rotation.eulerAngles;
print (baserot);
}
function Update () {
//rotates back to home on the Y axis at yreturnspeed over deltaTime
//I use this with a very fast return speed because I want minimal deviation on Y, you might want to set and min and max similar to what is in my Fixed Update.
var wantedrotation = Vector3(transform.rotation.eulerAngles.x, baserot.y, transform.rotation.eulerAngles.z);
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(wantedrotation), Time.deltaTime * yreturnspeed);
};
function FixedUpdate () {
//the rest is X constraint with min and max, I used this with a slower return because in other scripts I have rotation on X when moving.
if(transform.rotation.x < xmin) {
transform.rotation.x = xmin;
}
else if (transform.rotation.x > xmax) {
transform.rotation.x = xmax;
}
var wantedrotation = Vector3(baserot.x, transform.rotation.eulerAngles.y, transform.rotation.eulerAngles.z);
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(wantedrotation), Time.deltaTime * xreturnspeed);
}
I imagine that would become really taxing on the cpu time if you had hundreds of objects running this script. At most I may have 20-30 of these objects at the same time, but still, every Update and FixedUpdate function adds up.
Answer by beautyfullcastle · Aug 06, 2015 at 12:52 PM
I had a same problem. So I fixed it with this code. And It rotate only y axis.
function FixedUpdate() { GetComponent.().rotation.x = 0f; GetComponent.().rotation.z = 0f; }
I did much the same, like this:
Quaternion rot = r.rotation;
rot.x = 0;
rot.z = 0;
r.rotation = rot;
rot = this.transform.rotation;
rot.x = 0;
rot.z = 0;
this.transform.rotation = rot;
However, this can sometimes cause a strange "rotation quaternions must be unit length" issue.
Be sure and remember: Quaternion angles != euler angles. It would be better to record the Quaternion.eulerAngles into a Vector3 and then set the values to zero:
//Convert rotation into readable angles.
Vector3 eulerRotation = transform.rotation.eulerAngles;
//Set non essential angles to 0.
eulerRotation.x = 0;
eulerRotation.z = 0;
//Reset the transform rotation.
transform.rotation = Quaternion.Euler(eulerRotation);
Nice -- ultimately that is what I wound up doing in order to get around the issue. I figured that something as generalized as zero would have the same meaning in both quaternion and euler angles. But it seems like in some cases... not?
Answer by j_zeitler · Feb 10, 2016 at 05:39 PM
We can also read from the constraints bits if they change in runtime (can be done like this) or if we want our artist/rigger/animator to be able to change the constraints from the editor:
byte bits = (byte)rigidbody.constraints;
if ((bits & (1 << 1)) != 0)
Debug.Log("x position frozen");
if ((bits & (1 << 2)) != 0)
Debug.Log("y position frozen");
if ((bits & (1 << 3)) != 0)
Debug.Log("z position frozen");
if ((bits & (1 << 4)) != 0)
Debug.Log("x rotation frozen");
if ((bits & (1 << 5)) != 0)
Debug.Log("y rotation frozen");
if ((bits & (1 << 6)) != 0)
Debug.Log("z rotation frozen");
We can use this information to make a hacky override to our objects localRotation:
// save startRotation during Start() or something
byte bits = (byte)rigidbody.constraints;
Quaternion frozenRotation= new Quaternion(
(bits & (1 << 4)) != 0 ? startRotation.x : transform.localRotation.x,
(bits & (1 << 5)) != 0 ? startRotation.y : transform.localRotation.y,
(bits & (1 << 6)) != 0 ? startRotation.z : transform.localRotation.z,
transform.localRotation.w
);
transform.localRotation = frozenRotation;
Note: setting transform.localRotation.w as the w component will be slightly off, since that holds the total rotation magnitude before we clamped the rotation back to the start rotation... I think.
Answer by ZenMicro · Mar 06, 2016 at 02:44 PM
I am not 100% sure, but for me i changed the collider to a cube and the issue seems to be resolved, Has anyone tried this? even just for the lowest part collider of whatever your model is?