- Home /
Figuring out the correct amount of torque to apply?
How do I figure out how much torque is needed to my object to get it to match the rotation of another object in the scene?
I'm trying to use torque to get the position of one Rigid body to match the position of another object elsewhere in the scene.
.MoveRotation technically worked, but it jitters around a lot and it doesn't seem to play well with gravity. I don't mind if my object doesn't have the exact rotation of the other one, I just want it generally in the same spot, which is why I'm trying to use torque.
I've got a script on one object which has the transform of a second object.
public Transform match;
void FixedUpdate()
{
Vector3 t = ? // How do I get from transform.rotation to match.rotation?
transform.rigidbody.AddTorque(t, ForceMode.Impulse);
}
Update:
This is getting closer, but it's still not quite right. It starts rotating in the direction, but I expected it to overshoot and come back and sort of wobble, but it didn't do that. It just keeps spinning.
using UnityEngine;
using System.Collections;
public class RotateOnClick : MonoBehaviour {
public Transform match;
void FixedUpdate()
{
if (Input.GetMouseButtonUp(0))
{
Vector3 to = match.localRotation.eulerAngles.normalized;
Vector3 fr = (transform.rotation.eulerAngles == Vector3.zero) ? Vector3.up : rigidbody.rotation.eulerAngles.normalized;
Quaternion deltaQuat = Quaternion.FromToRotation(fr, to);
Debug.Log("From: " + fr + " to: " + to + " delta: " + deltaQuat);
Vector3 x = Vector3.Cross(fr, to);
float theta = Mathf.Asin(x.magnitude);
Vector3 w = x.normalized * theta / Time.fixedDeltaTime;
Quaternion q = transform.rotation * rigidbody.inertiaTensorRotation;
Vector3 T = q * Vector3.Scale(rigidbody.inertiaTensor, (Quaternion.Inverse(q) * w));
rigidbody.AddTorque(T, ForceMode.Impulse);
}
}
}
Why not just measure the amount of torque from one and apply it to the other and just play with a scale until they act similar enough?
The other object doesn't have torque applied to it. It's just at a particular rotation. If I copied it over, it would probably just be zero.
Answer by aldonaletto · Sep 29, 2011 at 09:31 PM
AddTorque is like AddForce: it applies an acceleration to the rigidbody, which increases the velocity over time. It's much easier to copy its angularVelocity:
void FixedUpdate(){ rigidbody.angularVelocity = match.rigidbody.angularVelocity; }But this only copy the physics effects: if you rotate match using Rotate or other non-physics method, nothing happens. If you need to make the object follow any match rotation, just copy the transform.rotation directly:
void FixedUpdate(){ transform.rotation = match.rotation; }You can even add some inertia using Lerp:
void FixedUpdate(){ transform.rotation = Quaternion.Lerp(transform.rotation, match.rotation, 5*Time.deltaTime); }
I wasn't totally clear in the first post. The match object isn't a physics object. It's just a standard one that I'm trying to match. It won't have a rigidbody to copy off of. If it did it would have to be kinemetic and I don't think it would have an angularVelocity.
I want to copy it's rotation using forces so that it can be affected by other forces, but generally keep the same shape most of the time.
Is the match object rotating at a constant rotation and around a fixed axis? Or it can rotate to any direction?
The match object doesn't have to move, but can rotate in any direction.
Answer by Tehelee · Jun 05, 2018 at 10:39 AM
I'm sure I'm not the only one to end up here recently; here's my springy rotation lock component. It functions similarly to the Spring Joint but for rotation:
[RequireComponent(typeof(Rigidbody))]
public class SpringRotation : MonoBehaviour
{
public float force = 10f;
public Rigidbody target;
private new Rigidbody rigidbody;
private Vector3 torque;
private void Awake()
{
this.rigidbody = this.GetComponent<Rigidbody>();
}
private void FixedUpdate()
{
if ((null == target) || !target) return;
// Determine Quaternion 'difference'
// The conversion to euler demands we check each axis
Vector3 torqueF = OrientTorque(Quaternion.FromToRotation(this.transform.forward, this.target.transform.forward).eulerAngles);
Vector3 torqueR = OrientTorque(Quaternion.FromToRotation(this.transform.right, this.target.transform.right).eulerAngles);
Vector3 torqueU = OrientTorque(Quaternion.FromToRotation(this.transform.up, this.target.transform.up).eulerAngles);
float magF = torqueF.magnitude;
float magR = torqueR.magnitude;
float magU = torqueU.magnitude;
// Here we pick the axis with the least amount of rotation to use as our torque.
this.torque = magF < magR ? (magF < magU ? torqueF : torqueU) : (magR < magU ? torqueR : torqueU);
this.rigidbody.AddTorque(this.torque * Time.fixedDeltaTime * force);
}
private Vector3 OrientTorque(Vector3 torque)
{
// Quaternion's Euler conversion results in (0-360)
// For torque, we need -180 to 180.
return new Vector3
(
torque.x > 180f ? 180f - torque.x : torque.x,
torque.y > 180f ? 180f - torque.y : torque.y,
torque.z > 180f ? 180f - torque.z : torque.z
);
}
}
perhaps that was ment to be the following for the OrientTorque
return new UnityEngine.Vector3(
180.0f < torque.x ? torque.x - 360.0f : torque.x,
180.0f < torque.y ? torque.y - 360.0f : torque.y,
180.0f < torque.z ? torque.z - 360.0f : torque.z
);