- Home /
Question by
NightyTheVampire · Jun 14, 2021 at 08:43 PM ·
rigidbodycharactercontrollervelocitycharacter movement
How would I go about keeping velocity in the air with this but allowing it to be controlled slightly in air?
Heres the code I used its a slightly modified version of the old very popular Rigidbody controller.
[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(CapsuleCollider))]
public class CharacterControls : MonoBehaviour
{
public float walkSpeed = 10.0f; //Set this to what speed is or everything will be fricked up
public float speed = 10.0f; //Make sure this matches walkSpeed
public float maxVelocityChange = 10.0f;
public bool canJump = true;
public float jumpHeight = 2.0f;
public Transform playerBody;
public float groundDistance = 0.4f;
public float airSpeed = 5.0f;
public float gravity = 15.0f;
public Transform groundCheck;
public LayerMask groundMask;
public float sprintSpeed = 13.0f;
bool isGrounded;
void Start()
{
}
void Awake()
{
GetComponent<Rigidbody>().freezeRotation = true;
GetComponent<Rigidbody>().useGravity = false;
}
void Update()
{
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
if (isGrounded)
{
Vector3 velocity = GetComponent<Rigidbody>().velocity;
Vector3 targetVelocity = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
targetVelocity = transform.TransformDirection(targetVelocity);
targetVelocity *= speed;
Vector3 velocityChange = (targetVelocity - velocity);
velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange);
velocityChange.y = 0;
GetComponent<Rigidbody>().AddForce(velocityChange, ForceMode.VelocityChange);
// Jump
if (isGrounded && Input.GetButton("Jump") && canJump)
{
GetComponent<Rigidbody>().velocity = new Vector3(velocity.x, CalculateJumpVerticalSpeed(), velocity.z);
}
}
if (Input.GetKey(KeyCode.LeftShift)==true && isGrounded)
{
speed = sprintSpeed;
}
if (Input.GetKey(KeyCode.LeftShift)==false)
{
speed = walkSpeed;
}
GetComponent<Rigidbody>().AddForce(new Vector3(0, -gravity * GetComponent<Rigidbody>().mass, 0));
}
float CalculateJumpVerticalSpeed()
{
return Mathf.Sqrt(2 * jumpHeight * gravity);
}
}
Comment
Have a raycast cast to ground everyframe to check if rigidbody/collider is touching the ground.
If not, you know its is flying in the air. Then stop taking player input
Then cache the velocity from the ground. Since no additional force was added, We add little force of tiny fraction from original movement based player keyboard movement.
Answer by Patrickmol · Jun 16, 2021 at 07:28 AM
//THIS IS THE EASIEST SOLUTION, PUT THIS CHUNCK AT THE LAST LINE OF THE UPDATE FUNCTION
float slowDown = 10; //PUT THIS AS CLASS VARIABLE, IF YOU WANT PUBLIC SO YOU CAN EDIT IT IN
//THE INSPECTOR
if (!isGrounded)
walkSpeed *= 1.0f/slowDown;