RigidBody.AddTorque(torqueAmount, Forcemode.Impulse) to Rotate Hinge Door to Desired Angle?

I am trying to figure out how to calculate the amount of torque to add to a physics door to make it open perfectly.

I have a simple physics-based hinge door set up in my game:

More Images Of The Door

The door’s Box collider:

The door’s RigidBody:

The door’s HingeJoint:

I would like to give the PhysicsDoor script a function that uses RigidBody.AddTorque() with ForceMode.Impulse to rotate the door to exactly the max limit of the HingeJoint. My problem is that I want to only call RigidBody.AddTorque() once, not every FixedUpdate() or something.

I have been at this for a while and can’t find anything that works or any posts that answer this question.

What Have I Tried?

I have tried the following inside rb.AddTorque(Vector3.up * [equation below], ForceMode.Impulse);:

  • (desiredYRotation - currentYRotation) * rb.mass;
  • (desiredYRotation - currentYRotation) * rb.mass * rb.drag;
  • (desiredYRotation - currentYRotation) * rb.mass * rb.drag * rb.angularVelocity;
  • (desiredYRotation - currentYRotation) * rb.mass * (1 + rb.drag) * (1 + rb.angularVelocity);

These are very stupid things to try, but I tried them anyway.

I have been realizing through my tests that I probably need to account for those forces as they are applied over time, rather than just those easy numbers. This is because when the drag or angularDrag is low, the force is too great, but when either or both are high, the force is too small.

SUMMARY OF WHAT I AM TRYING TO ACCOMPLISH

I am trying to calculate the amount of torque that I need to apply ONCE as an impulse in order to rotate a hinge door a desired amount of degrees.

POSSIBLY USEFUL INFORMATION

I don’t know much about physics so if you do, pardon my ignorance.

I think that the end result will probably be some kind of equation that uses the mass, the opposing forces, and the time it will take to rotate (likely deduced using the opposing forces), to find the correct amount of torque to apply.

Something like this maybe:
torqueAmount = [amount to rotate] * rb.mass * (1 + rb.drag) * (1 + rb.angularDrag) * timeToRotate;
(using 1+ for the drags since I think that’s the right thing… idk)

Here is the line of code I am using to apply the torque:
rb.AddTorque(Vector3.up * torqueAmount, ForceMode.Impulse);

It could also use the HingeJoint’s massScale or whatever that does.

Thank You For Reading! If you can help me, thank you again!

P.S. if this didn't make sense, I can try to offer clarification, it may take a few days though...

Probably not what you want to hear, but the most straight forward way I can think of is to apply torque in FixedUpdate that you decrease steadily as you get to your target rotation.

Of course if you only want to do it once, you could rather than try and calculate it, just test a bunch of different values until you get the one provides the desired result.

Could you explain where you got the drag equations?

Usually, drag is proportional to velocity, so I’m assuming that angular drag is proportional to angular velocity (which I can see in your equation). That is the force of drag at a given moment.

What you want is for the energy loss due to drag from starting angle to ending angle to equal the amount of kinetic energy of the door. That way, the door is stopped (used up all its kinetic energy) by the time it reaches the ending angle.

  1. Kinetic energy will be from this equation: Rotational energy - Wikipedia
  2. Energy due to a torque is Torque * Angle. In this case, drag torque will not be constant. You will need to integrate the torque from startingAngle to endingAngle.

Here are a couple equations:

startingKineticEnergy + dragEnergy = 0
startingKineticEnergy = 1/2 * momentOfInertia * startingAngularVelocity * startingAngularVelocity
dragEnergy = (integral of drag equation from [startingAngle, endingAngle])

The dragEnergy will be in terms of angular velocity, so you’ll need to calculate the velocity in terms of angle.

Instead of using ForceMode.Impulse you should use ForceMode.VelocityChange and then you can apply the torque like so:

rb.AddTorque(Vector3.up * rotateAmount * Mathf.Deg2Rad * rb.angularDrag, ForceMode.VelocityChange);

Keep in mind that it can’t be perfect because the physics engine moves objects in steps/frames. But the higher the physics frame rate the more precise it will be.

I got the drag equations from no where… I just made them up.

Thank you for explaining how this works. I read up on the stuff and it still doesn’t make sense (I’m bad at physics, but I’m learning). I’m going to go with a less intelligent approach since I don’t want to spend more time working on a door and the easy way works well enough for me.

Thank you again for showing me this.

It’s not perfect, but it deffinately works (almost perfectly). I ended up using something like this with a “magnet” to make the door snap into place when it’s close enough.

Thank you

Configurable joint with target rotation is probably the best solution here. No need to math anything. Just assign the correct axis, target, and drive values.