Rotating an object to a specific point with addtorque

Viewed 601

I am trying to make a space game, but I don't know how to rotate my spacecraft to a specific point in vector3 whith addtorque.

For example, to kill the velocity, my current script to calculate the trajectory is this

using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(Rigidbody))]

public class CalculateTrajectory : MonoBehaviour
{
    Vector3 Direction;
    // Start is called before the first frame update
    void Start()
    {
        Rigidbody rb = GetComponent<Rigidbody>();
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        Rigidbody rb = GetComponent<Rigidbody>();
        Vector3 trajectory = rb.velocity; // Velocity of gameObject (Vector3)
        Vector3 NextPosition = transform.position + trajectory;
        Vector3 Direction = (NextPosition - transform.position) * 1000;
        Debug.DrawRay(transform.position, Direction, Color.green, 0.2f);
    }
}

(sorry for my bad English I'm a 14 year old student from Germany)

1 Answers

You need to find the axis of rotation to get from the current heading (eg, transform.forward to the desired heading (rb.velocity if I correctly understand your goal). This can be found using the cross product:

// Note: will be scaled by the sine of the angle between the two vectors
var axis = Vector3.Cross (transform.forward, rb.velocity.normalized);

This can then be scaled by the desired torque which is then applied to the rigid body via AddTorque to give a proportional feedback. That is, this acts much like a spring. However, this will get weaker for angles > 90 degrees (see below)

var torque = axis * torqueFactor;

You might want to factor in the rigid body's angular velocity to include some damping. This can be done by subtracting the rigid body's angular velocity vector (scaled by some factor).

torque -= rb.angularVelocity * dampingFactor;

Note that finding good values for torqueFactor and dampingFactor can take some tweaking, and depends on the rigid body's moment of inertia (combination of mass and shape).

The problem with angles > 90 degrees: When the angle is between 90 degrees and 180, the torque will drop off again as the angle approaches 180 degrees. This can be handled by computing the sine of the half angle, which can be done directly from the vectors:

// returns the sin(half angle between a and b).
// Loses the sign (thus direction) of the angle.
float HalfSin(Vector3 a, Vector3 b)
{
    a = a.normalized;
    b = b.normalized;
    // (a - b).magnitude gives 2*sin(angle/2)
    // using + will give 2*cos(angle/2)
    return (a - b).magnitude * 0.5f;
}

This can then be used to scale the normalized result of the cross product of the two angles to get both direction and magnitude of the half-angle, and will be 0 at 0 degrees and 1 at 180 degrees (or would be if not for issues with normalizing the 0-vectors resulting from the cross product of parallel vectors).

Using the above ideas, this is my replacement for unity's FromToRotation (because it falls apart for very small angles due the normalization problem):

    Quaternion fromtorot(Vector3 a, Vector3 b)
    {
        float ma = a.magnitude;
        float mb = b.magnitude;
        Vector3 mb_a = mb * a;
        Vector3 ma_b = ma * b;
        float den = 2 * ma * mb;
        float mba_mab = (mb_a + ma_b).magnitude;
        float c = mba_mab / den; // cosine of half angle
        // find the rotation axis scaled by the sine of the half angle (s)
        // using |a x b| = sin(angle) |a| |b| = 2 c s |a| |b|
        // where c and s are the cosine and sine of the half hangle
        // and mba_mab is 2 c |a| |b|
        // c is not 0 until 180 degrees (vectors are anti-parallel)
        Vector3 v = Vector3.Cross (a, b) / mba_mab;
        return new Quaternion(v.x, v.y, v.z, c);
    }

It behaves very well near 0 degrees, but does fall apart near 180 degrees, but that is to be expected: the axis of rotation is not defined. An undefined rotation axis is not a problem at 0 degrees, but is a very big problem at 180 degrees (try turning a book by 180 degrees about the X, Y and Z axes, or anything in between: very different results).

Related