Noob question: Why doesn't velocity reduce?

Q1: Why does rigidbody.velocity.magnitude not represent speed when equalising inverse directional thrust? I expected some kind of reduction.
Q2: When my object collides, magnitude isn’t bounced, am I misunderstanding what magnitude represents?

Scenario:
(I’m in zero gravity, with 0.5 angular drag)

If I turn 180 degrees whilst my velocity is 10, I would expect that my ship would head towards ‘0’, maybe not fully due to inertia, and then go back up to 10 - but it’s not. It’s still near enough 10.

I even see the ground stop moving, confirming that I am effectively stationary, but the velocity magnitude never gets anywhere near 0.
If I slam into a wall, the magnitude still thinks it’s moving at the same speed. Even though my object is blatantly static.
Everyone on the forums swears that velocity.magnitude is your speed. Not for me!

(rigidBody = GetComponent())

    private void FixedUpdate()
    {
        rigidBody.AddRelativeTorque(new Vector3(Input.GetAxis("Vertical") * 2.0f, 0, -Input.GetAxis("Horizontal")));

        float fThrustApplied = 1.0f;

        rigidBody.AddForce(transform.forward * fThrustApplied, ForceMode.Force);

        if (rigidBody.velocity.magnitude > 30f)
            rigidBody.velocity = rigidBody.velocity.normalized * 30f; // I don't know why normalized is used?

        // TextUI control. Actual speed seems to be right, but when I turn 180' I expected it to go to zero before getting bigger again.
        // it's also not zero when I hit something and bounce off it
        axisText.text = " ActualSpeed:" + rigidBody.velocity.magnitude.ToString();
    }

I think this is an issue with basic vector math.

Rigidbody.velocity is a 3D vector (Vector3) with components x, y, z. Each component represent the velocity in m/s along that axis. If the object moves straight along the global (world) z vector, then the speed will be at the z component while x and y will be zero.

The magnitude of a vector represent its length. It’s always zero or a positive number. Whenever your object is moving, rigidbody.velocity.magnitude will be the absolute speed of movement in m/s, no matter where your object is heading to. Note that very small speeds may be represented with exponential notation, such as 1.3456E-5, which is indeed 0.000013456, but the exponential notation might make it look bigger at first sight.

The normalized property returns a vector in the same direction of the actual vector, but with length 1. Thus, rigidbody.velocity.normalized.magnitude is always exactly 1. In your case, you’re setting the velocity in the same direction of the original velocity but with length (magnitude, speed) of 30.

If you want to measure the forward speed only, you can do so easily with Vector3.Dot(transform.forward, rigidbody.velocity).

Hope this helps.

That’s a brilliant explanation, and I shall stop guessing and learn some basic vector transforms before trying to hack again.

As for my magnitude not reducing - turns out if you use the Asset Store example assets you can get yourself into trouble - the spaceship scene had some mobile input controllers that were continually messing with my physics (on my laptop) to the point that the rigid body.transform was going MENTAL, flicking between 0 and 1, and not causing magnitude to be reduced when collisions happen. I deleted the entire scene and started again with the same script of mine and things worked!

@Edy Thanks for the tip… here’s a demo using that little forward speed trick, and I’ve added some auto-adjustment of the velocity so that it eventually lines up with the forward motion. Thoughts welcome.

This will take a little while to load - press G to start moving.
https://dl.dropboxusercontent.com/u/79636404/spacecontrol/index.html

// press 1 or 2 to view different cameras
    Rigidbody rigidBody;
    public List<GameObject> cameras = new List<GameObject>();
    private int currentCamera = 0;

    public UnityEngine.UI.Text speed;
    public UnityEngine.UI.Text targetSpeed;
    public UnityEngine.UI.Text debugText;

    void Start()
    {
        rigidBody = GetComponent<Rigidbody>();

        // theres a weird bug with box colliders affecting roll/force - so re-set it
        // http://forum.unity3d.com/threads/adding-a-collider-stops-rotation.42640/
        rigidBody.inertiaTensor = new Vector3(1, 1, 1);
    }
    private float fTargetSpeed = 0.0f;

    private void FixedUpdate()
    {
        rigidBody.AddRelativeTorque(new Vector3(Input.GetAxis("Vertical"), 0, -Input.GetAxis("Horizontal")*0.5f));
     

        // thanks to Edy for this gem
        float fForwardSpeed = Vector3.Dot(transform.forward, rigidBody.velocity);

     
        if (fForwardSpeed > fTargetSpeed)
            rigidBody.AddForce(transform.forward * -5.0f, ForceMode.Force);
        else
            rigidBody.AddForce(transform.forward * 5.0f, ForceMode.Force);
    

        // ensure we apply forces to make our velocity edge towards our normalized forward vector
        Vector3 vMovement = rigidBody.velocity.normalized;
        Vector3 vFacing = transform.forward;

        Vector3 diff = vFacing-vMovement;
        // apply a gentle push in the opposing direction.
        rigidBody.AddForce(diff * 4.0f);

        speed.text = ((int)fForwardSpeed).ToString()+"m/s";
        targetSpeed.text = fTargetSpeed.ToString();
        debugText.text = "forward: " + vFacing.ToString() + " vel:" + vMovement.ToString() + " gap:" + diff.ToString();
     
    }

    private void Update()
    {
        // G for go go go
        if (Input.GetKeyUp(KeyCode.G))
            fTargetSpeed += 5.0f;
        if (Input.GetKeyUp(KeyCode.B))
            fTargetSpeed -= 5.0f;

        if (Input.GetKeyUp(KeyCode.Alpha1))
        {
            cameras[currentCamera].SetActive(false);
            currentCamera++;
            currentCamera = currentCamera % cameras.Count;

            cameras[currentCamera].SetActive(true);
        }
    }