Limiting Speed on Two Axis

Hello,

I am trying to make a character controller that moves based on adding force to the Rigidbody. I have all the movement working except for one part. I want to limit the speed the object can move but I only want to limit the X and the Z axis. I want to leave the Y axis either unlimited or a higher limit than the others. The character will jump and so the Y axis can’t be added in to the speed limit.

Here is the code. Everything here works, I just need to add something to get the speed limit. The movement is in the Fixed Update, so you can ignore everything else.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement : MonoBehaviour {

    public float runAcceleration;
    public float maxRunSpeed;
    public float runStopSpeed;
    public float jumpHeight;
    public float horizontalSensitivity; //Sensitivity for the mouse movement.
    public float verticalSensitivity; //Sensitivity for the mouse movement.

    public bool invertLook; //Make true if the player wants to invert their camera X movement.

    float rotationX; //Used for clamping the X rotation of the camera.

    Rigidbody rb;
    Camera cam; //Just gets the camera for mouse movement.
    GameObject groundCheck;
    CapsuleCollider playerCapsule;

    Vector3 forwardVelocity;
    Vector3 sidewaysVelocity;

    // Use this for initialization
    void Start ()
    {
        rb = GetComponent<Rigidbody>();
        groundCheck = GameObject.FindGameObjectWithTag("groundCheck");
        cam = GetComponentInChildren<Camera>(); //Gets the camera.
        playerCapsule = GetComponent<CapsuleCollider>();
    }
	
	// Update is called once per frame
    void Update()
    {
        //***Jump Command***
        if (Input.GetButtonDown("Jump") && groundCheck.GetComponent<GroundChecker>().playerGrounded)
        {
            Jump();
        }
        //***End of Jump Command***

        //***Character/Camera Rotation***
        transform.Rotate(new Vector3(0, Input.GetAxis("Mouse X"), 0) * Time.deltaTime * (horizontalSensitivity * 10)); //Rotate the player based on sensitivity with mouse.
        transform.Rotate(new Vector3(0, Input.GetAxis("Horizontal2"), 0) * Time.deltaTime * (horizontalSensitivity * 10)); //Rotate the player based on sensitivity with controller.

        rotationX += Input.GetAxis("Mouse Y") * Time.deltaTime * (verticalSensitivity * 10); //Rotate the camera up and down based on sensitivity with mouse.
        rotationX += Input.GetAxis("Vertical2") * Time.deltaTime * (verticalSensitivity * 10); //Rotate the camera up and down based on sensitivity with controller.
        rotationX = Mathf.Clamp(rotationX, -80, 80); //Clamp the camera so it can't rotate too far.

        if (invertLook)
        {
            cam.transform.localEulerAngles = new Vector3(rotationX, transform.rotation.y, transform.rotation.z); //Up and down movement for inverted players.
        }
        else
        {
            cam.transform.localEulerAngles = new Vector3(-rotationX, transform.rotation.y, transform.rotation.z); //Up and down movement for non-inverted players.
        }
        //***End of Character/Camera Rotation***
    }

    void FixedUpdate ()
    {
        //***Player Movement***
        forwardVelocity = transform.forward * Input.GetAxis("Vertical") * runAcceleration; //Gets the forward velocity based on direction pressed and acceleration.
        forwardVelocity.y = rb.velocity.y / 2;
        sidewaysVelocity = transform.right * Input.GetAxis("Horizontal") * runAcceleration; //Gets the sideways velocity based on direction pressed and acceleration.
        sidewaysVelocity.y = rb.velocity.y / 2;
        rb.AddForce(forwardVelocity + sidewaysVelocity);
        if (Input.GetAxis("Horizontal") > -0.1f && Input.GetAxis("Horizontal") < 0.1f && Input.GetAxis("Vertical") > -0.1f && Input.GetAxis("Vertical") < 0.1f)
        {
            rb.velocity = new Vector3 (Mathf.Lerp(rb.velocity.x, 0, runStopSpeed), rb.velocity.y, Mathf.Lerp(rb.velocity.z, 0, runStopSpeed));
        }
        //***End of Player Movement***
    }

    void Jump()
    {
        rb.AddForce(0, jumpHeight, 0, ForceMode.Impulse);
    }
}

If I understand your question correctly, then perhaps something like this would do the job.

// Store the current y velocity so we can restore it later.
float tempY = rb.velocity.y;

// Then remove it completely.
rb.velocity.y = 0;

// Now with just the x and z axis in the velocity apply the speed limitation.
if(rb.velocity.magnitude > speedLimit)
{
	rb.velocity = rb.velocity.normalized * speedLimit;
}

// Then restore the y component of the velocity, which will be unrestricted.
rb.velocity.y = tempY;

The idea is to remove the y from the velocity before applying the speed restriction, and then restore the y component afterwards so that it is unaffected by the restriction.