Smooth movement using joystick in Unity3D - c#

I try to accomplish smooth movement with the Xbox Controller, however it is very snappy, even though snap is turned of and deadzone set to 0. Movement with keyboard however is very smooth, so I assume GetAxis does not work with a controller, it's always GetAxisRaw. So I switched to GetAxisRaw and tried to smooth everything out. Even with acceleration, the movement is still very jagged and snappy. Does anyone have an idea how to get a nice smooth movement with a controller, like keyboard + GetAxis?
public class PlayerController : MonoBehaviour
{
CharacterController cc;
float acceleration = 0;
[SerializeField] float speed;
[SerializeField] float acclerationRate = 1;
private void Awake()
{
cc = GetComponent<CharacterController>();
}
private void Update()
{
float deadzone = 0f;
Vector2 stickInput = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
if (stickInput.magnitude < deadzone)
stickInput = Vector2.zero;
else
stickInput = stickInput.normalized * ((stickInput.magnitude - deadzone) / (1 - deadzone));
if (stickInput.x != 0 || stickInput.y != 0)
{
acceleration += Time.deltaTime * acclerationRate;
acceleration = Mathf.Clamp01(acceleration);
}
else
{
acceleration = 0;
}
cc.Move(new Vector3(stickInput.x, 0, stickInput.y) * speed * acceleration * Time.deltaTime);
}
}

I would keep track of your player's velocity and use MoveTowards to adjust it based on the input. Don't forget to clamp your input's magnitude so your character doesn't travel diagonally faster than orthogonally in the event the player prefers keyboard input.
CharacterController cc;
[SerializeField] float speed;
[SerializeField] float acclerationRate = 1;
[SerializeField] float deadzone = 0f;
Vector3 velocity;
private void Awake()
{
cc = GetComponent<CharacterController>();
velocity = Vector3.zero;
}
private void Update()
{
Vector3 stickInput = new Vector3(Input.GetAxisRaw("Horizontal"), 0f,
Input.GetAxisRaw("Vertical"));
if (stickInput.magnitude < deadzone)
}
stickInput = Vector3.zero;
}
else
{
float clampedMag = Mathf.Min(1f, stickInput.magnitude);
stickInput = stickInput.normalized * (clampedMag - deadzone) / (1f - deadzone);
}
velocity = Vector3.MoveTowards(velocity, stickInput,
accelerationRate * Time.deltaTime);
cc.Move(velocity * Time.deltaTime);
}

Related

How do I change my direction towards rotation angle at all times?

I have this script below and I want my player to always move towards the rotation angle, which doesn't happen. It only changes direction when I click.
My purpose is for the player to move at all times and towards the rotation which should be controlled by mouse position/mouse x axis (kind of like auto-run, but always change rotation based on mouse, not just move right or left).
I've tried about 10 different methods, nothing worked so far...
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MovementController : MonoBehaviour
{
public float speed = 4;
public float rot = 0f;
public float rotSpeed = 80;
public float gravity = 8;
private Camera cam;
Vector3 moveDir = Vector3.zero;
CharacterController controller;
Animator anim;
// Start is called before the first frame update
void Start()
{
controller = GetComponent<CharacterController> ();
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
float horizontalSpeed = 8.0f;
//Get the mouse delta. This is not in the range -1...1
float h = horizontalSpeed * Input.GetAxis("Mouse X");
float z = horizontalSpeed * Input.GetAxis("Mouse Y");
transform.Rotate(0, h, 0);
//Move Input
if(controller.isGrounded){
if(Input.GetMouseButtonUp(1))
{
anim.SetInteger ("condition", 1);
moveDir = new Vector3 (0,0,1) * speed;
// moveDir *= speed;
moveDir = transform.TransformDirection(moveDir);
}
if(Input.GetMouseButtonDown(1))
{
anim.SetInteger("condition", 0);
moveDir = Vector3.zero;
}
}
moveDir.y -= gravity * Time.deltaTime;
controller.Move(moveDir * Time.deltaTime);
}
}
Transform.LookAt
Just get a cursor position and that's it
Vector3 direction = target.position - player.transform.position;
Quaternion finalPlayerRotation = Quaternion.LookRotation(direction);
player.transform.rotation = finalPlayerRotation;
This also works in some cases:
Vector3 direction = target.position - player.transform.position;
player.transform.right /*You may need to change the Right to upper, -upper, -Right depend on the player rotation and the target position*/ = direction;

Unity rigidbody collision not working properly

Im having a lot of weird prolems with my rigidbody collision in unity. I have a player controller script which allows me to move my player, but when it collides with stairs, it glitches out. when it collides with a door, it glitches out and when it collides with 2 nvisible box colliders at the edge of the map while walking diagonally, it walks through one of them. Ive searched around quite a bit but couldn't find anything. I know it's not a lot to go on, but here is some stuff that might help:
a video of what happens exactly
the character controller code:
using System;
using UnityEngine;
public class PlayerController : MonoBehaviour{
public Rigidbody body;
//player movement
private float speed = 12f;
private float walkSpeed = 10;
private float runSpeed = 15;
private float gravity = -9.81f;
public float jumpHeight = 2f;
private Vector3 inputs;
//player rotation
private float targetAngle = 0f;
private float angle = 0f;
public float turnSmoothTime = .1f;
public float turnSmoothVelocity;
//player jump
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;
private bool isGrounded;
//there are 6 possible directions for gravity; positive and negative x, y and z. The direction can therefore be -3, -2, -1, 1, 2 or 3 where 1=y, 2=x, 3=z
public int direction = 1;
public void movePlayer(Vector2 movement){
float horizontal = movement.x;
float vertical = movement.y;
//check if the player is standing on the ground
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
Quaternion rotation = new Quaternion();
body.freezeRotation = true;
if (Mathf.Abs(direction) == 1){
//gravity in y direction
//set the direction of the gravity
Physics.gravity = new Vector3(0f, direction * gravity, 0f);
//set the direction the inputs should work in
inputs.x = horizontal;
inputs.z = vertical;
inputs.y = body.velocity.y;
//calculate the angle with which the player has to be rotated and make the rotation smooth (smoothing is only possible in this orientation)
targetAngle = Mathf.Atan2(inputs.x, inputs.z) * Mathf.Rad2Deg;
angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime);
//set the characters rotation
rotation = Quaternion.Euler(0f, angle, 0f);
}
else if (Mathf.Abs(direction) == 2){
//gravity in x direction
Physics.gravity = new Vector3((direction / 2) * gravity, 0f, 0f);
inputs.y = -horizontal;
inputs.z = vertical;
inputs.x = body.velocity.x;
targetAngle = Mathf.Atan2(-inputs.y, inputs.z) * Mathf.Rad2Deg;
rotation = Quaternion.Euler(targetAngle, 0f, (direction / 2) * -90f);
}
else if (Mathf.Abs(direction) == 3){
//gravity in z-direction
Physics.gravity = new Vector3(0f, 0f, (direction / 3) * -gravity);
inputs.x = horizontal;
inputs.y = vertical;
inputs.z = body.velocity.z;
targetAngle = Mathf.Atan2(inputs.x, inputs.y) * Mathf.Rad2Deg;
//set the rotation in the correct order of the axis (90 degrees first and then around the correct axis)
rotation = Quaternion.AngleAxis((direction / 3) * -90f, Vector3.right) *
Quaternion.AngleAxis(0f, Vector3.forward) *
Quaternion.AngleAxis(targetAngle, Vector3.up);
}
else{
direction = 1;
}
/*
if (inputs != Vector3.zero){
body.velocity = inputs;
}*/
//rotate the player in the move direction as long as they are moving
if (inputs.magnitude >= 0.1f){
transform.rotation = rotation;
}
}
void FixedUpdate(){
//move the player
body.MovePosition(body.position + inputs * speed * Time.fixedDeltaTime);
}
public void flip(int changedDirection){
inputs = Vector3.zero;
angle = 0f;
targetAngle = 0f;
direction = changedDirection;
}
public void walk(){
if (isGrounded){
speed = walkSpeed;
}
}
public void run(){
if (isGrounded){
speed = runSpeed;
}
}
public void jump(){
if (isGrounded){
if (direction == 1){
body.velocity = new Vector3(inputs.x, jumpHeight, inputs.z);
}
else if (direction == 2){
body.velocity = new Vector3(jumpHeight, inputs.y, inputs.z);
}
else if (direction == 3){
body.velocity = new Vector3(inputs.x, inputs.y, jumpHeight);
}
}
}
}
A screenshot of my player object's important components:
P.S. the code has some weird gravty changing parts. Thats for the rest of the game, but it's not important for this question. Hopefully you guys can help me. Im happy to provide any other information you might need :) thanks for your time in advance!!
Edit: Commented out one part based on the first answer, but that din't fix it
First of all, you move your player 'twice', first inside movePlayer function you have:
//move the player
if (inputs != Vector3.zero){
body.velocity = inputs;
}
and then in every FixedUpdate:
body.MovePosition(body.position + inputs * speed * Time.fixedDeltaTime);
body.MovePosition moves yours player, but not zeroes velocity (which you set in movePlayer function).
By moving player this way you can 'overshoot' too small colider, so object will pass through.
You can add more drag to rigidbody to slowdown object a bit.
Okay so for anyone having similar problems, I found the answer:
The problem was that I was using body.moveposition, this should actually body.addforce.
This oes mean that you have to change some of the code. If you want further explanation because you had a similar problem, contact me, but here is my improved code to get you started:
using System;
using UnityEngine;
public class PlayerController : MonoBehaviour{
public Rigidbody body;
//player movement
private float speed = 12f;
private float walkSpeed = 10;
private float runSpeed = 15;
public float gravity = -9.81f;
public float jumpHeight = 2f;
private Vector3 inputs;
//player rotation
private float targetAngle = 0f;
private float angle = 0f;
public float turnSmoothTime = .1f;
public float turnSmoothVelocity;
//player jump
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;
private bool isGrounded;
//there are 6 possible directions for gravity; positive and negative x, y and z. The direction can therefore be -3, -2, -1, 1, 2 or 3 where 1=y, 2=x, 3=z
public int direction = 1;
public void movePlayer(Vector2 movement){
float horizontal = movement.x;
float vertical = movement.y;
//check if the player is standing on the ground
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
Quaternion rotation = new Quaternion();
body.freezeRotation = true;
if (Mathf.Abs(direction) == 1){
//gravity in y direction
//set the direction of the gravity
Physics.gravity = new Vector3(0f, direction * gravity, 0f);
//set the direction the inputs should work in
inputs.x = horizontal;
inputs.z = vertical;
inputs.y = 0;
//calculate the angle with which the player has to be rotated and make the rotation smooth (smoothing is only possible in this orientation)
targetAngle = Mathf.Atan2(inputs.x, inputs.z) * Mathf.Rad2Deg;
angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime);
//set the characters rotation
rotation = Quaternion.Euler(0f, angle, 0f);
}
else if (Mathf.Abs(direction) == 2){
//gravity in x direction
Physics.gravity = new Vector3((direction / 2) * gravity, 0f, 0f);
inputs.y = -horizontal;
inputs.z = vertical;
inputs.x = body.velocity.x;
targetAngle = Mathf.Atan2(-inputs.y, inputs.z) * Mathf.Rad2Deg;
rotation = Quaternion.Euler(targetAngle, 0f, (direction / 2) * -90f);
}
else if (Mathf.Abs(direction) == 3){
//gravity in z-direction
Physics.gravity = new Vector3(0f, 0f, (direction / 3) * -gravity);
inputs.x = horizontal;
inputs.y = vertical;
inputs.z = body.velocity.z;
targetAngle = Mathf.Atan2(inputs.x, inputs.y) * Mathf.Rad2Deg;
//set the rotation in the correct order of the axis (90 degrees first and then around the correct axis)
rotation = Quaternion.AngleAxis((direction / 3) * -90f, Vector3.right) *
Quaternion.AngleAxis(0f, Vector3.forward) *
Quaternion.AngleAxis(targetAngle, Vector3.up);
}
else{
direction = 1;
}
//rotate the player in the move direction as long as they are moving
if (inputs.magnitude >= 0.1f){
transform.rotation = rotation;
}
}
void FixedUpdate(){
body.AddForce(inputs * speed * Time.fixedDeltaTime);
}
public void flip(int changedDirection){
inputs = Vector3.zero;
angle = 0f;
targetAngle = 0f;
direction = changedDirection;
}
public void walk(){
if (isGrounded){
speed = walkSpeed;
}
}
public void run(){
if (isGrounded){
speed = runSpeed;
}
}
public void jump(){
if (isGrounded){
if (direction == 1){
body.AddForce(new Vector3(0, jumpHeight, 0));
}
else if (direction == 2){
body.AddForce(new Vector3(jumpHeight, 0, 0));
}
else if (direction == 3){
body.AddForce(new Vector3(0,0 , jumpHeight));
}
}
}
}
For me this created some additionl problems with jump for example, so here are the values you need to tweak to fix those: the rigidbody mass and drag and the player controller gravity and jump height.

Unity grounded state is flickering for character. .isGrounded being used but still flickering

The grounded state for my character controller flickers on and off constantly at what seems to be every frame. From what I know, it's supposed to check if the player is grounded through player.isGrounded, but something else is moving it back up.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerCharacterController: MonoBehaviour {
static Animator anim;
public bool walking;
public GameObject playerModel, Hero;
//Transforms
public Transform playerCam, character, centerPoint;
private Vector3 moveDirection;
//character controller declaration
CharacterController player;
//Mouse Rotation
private float rotX, rotY;
//Mouse Y Position
public float mouseYPosition = 1f;
//Mouse Sensitivity
public float Sensitivity = 10f;
//Mouse Zoom
private float zoom;
public float zoomSpeed = 2;
//Clamping Zoom
public float zoomMin = -2f;
public float zoomMax = -10f;
public float rotationSpeed = 5f;
//Move Front Back left & Right
private float moveFB, moveLR;
//Movement Speed
public float Speed = 2f;
//Velocity of Gravity
public float verticalVelocity;
//Jump Distance
public float jumpDist = 5f;
//Multiple Jumps
int jumpTimes;
//To use with Dialogue Manager
public DialogueManager DiagM;
public AudioClip jumpSound;
public AudioClip HurtSound;
public AudioClip PunchSound;
AudioSource audioSource;
//knockback
public float knockBackForce;
public float knockBackTime;
private float knockBackCounter;
// Use this for initialization
void Start ()
{
//character controller
player = GameObject.Find("Player").GetComponent<CharacterController> ();
StartCoroutine(MyCoroutine(character));
anim = GetComponent<Animator>();
//mouse zoom
zoom = -3;
centerPoint.transform.position = playerCam.transform.position;
centerPoint.transform.parent = null;
audioSource = GetComponent<AudioSource>();
}
IEnumerator MyCoroutine (Transform character)
{
if (player.isGrounded == true)
{
anim.SetBool("isFalling",false);
//anim.SetBool("isIdling", true);
yield return new WaitForSeconds(0);
}
}
// Update is called once per frame
void Update ()
{
//Mouse Zoom Input
zoom += Input.GetAxis ("Mouse ScrollWheel") * zoomSpeed;
if (zoom > zoomMin)
zoom = zoomMin;
if (zoom < zoomMax)
zoom = zoomMax;
//Mouse Camera Input
playerCam.transform.localPosition = new Vector3 (0, 0, zoom);
//Mouse Rotation
rotX += Input.GetAxis ("Mouse X") * Sensitivity;
rotY -= Input.GetAxis ("Mouse Y") * Sensitivity;
//Clamp Camera
rotY = Mathf.Clamp (rotY, -60f, 60f);
playerCam.LookAt (centerPoint);
centerPoint.localRotation = Quaternion.Euler (rotY, rotX, 0);
//Movement Speed
if (knockBackCounter <= 0)
{
moveDirection = (transform.forward * Input.GetAxis("Vertical")) + (transform.right * Input.GetAxis("Horizontal"));
moveDirection = moveDirection * Speed;
moveDirection.y = verticalVelocity;
player.Move(moveDirection * Time.deltaTime);
//Movement Rotation
centerPoint.position = new Vector3 (character.position.x, character.position.y + mouseYPosition, character.position.z);
//knockback disable
//Movement Input
if (Input.GetAxis("Vertical") != 0 || Input.GetAxis("Horizontal") != 0)
{
transform.rotation = Quaternion.Euler(0f, centerPoint.rotation.eulerAngles.y, 0f);
Quaternion turnAngle = Quaternion.LookRotation(new Vector3(moveDirection.x, 0f, moveDirection.z));
playerModel.transform.rotation = Quaternion.Slerp(playerModel.transform.rotation, turnAngle, Time.deltaTime * rotationSpeed);
if (player.isGrounded == true)
{
anim.SetBool("isWalking", true);
anim.Play("Running");
}
}
else
{
StartCoroutine(MyCoroutine(character));
}
if (Input.GetButtonDown("LHand"))
{
audioSource.PlayOneShot(PunchSound, 1F);
anim.Play("RPunch");
}
if (player.isGrounded == true)
{
jumpTimes = 0;
//verticalVelocity = -Physics.gravity.y * Time.deltaTime;
verticalVelocity = 0;
}
else
{
verticalVelocity += Physics.gravity.y * Time.deltaTime;
anim.SetBool("isWalking", false);
anim.SetBool("isFalling", true);
}
if (jumpTimes < 1)
{
if (Input.GetButtonDown("Jump"))
{
verticalVelocity += jumpDist;
anim.Play("Jump");
audioSource.PlayOneShot(jumpSound, 1F);
jumpTimes += 1;
}
}
}
else
{
knockBackCounter -= Time.deltaTime;
}
}
public void Knockback(Vector3 direction)
{
knockBackCounter = knockBackTime;
anim.Play("Jump");
audioSource.PlayOneShot(HurtSound, 50F);
moveDirection = direction * knockBackForce;
moveDirection.y = knockBackForce;
}
}
It looks like it has to do with the verticalVelocity lines, but so far I have only tried setting verticalVelocity = 0 and that works until I have actually moved the character. What could I change to stop the flickering?
Probably it is already solved, but the reason for that is that if you are using Character Controller you should apply gravity ALL the time to the character.
When the character collides with a object, it actually enters a little bit inside this object, then Unity pushes the character back away from the object, until it is no longer touching it. At this point, your gravity starts acting again, and re initiziling the cycle.
You need to apply gravity 100% of the time to create enough force to "balance" this fight with the floor. Could be a smaller "gravity" like 1. No need to be your gravity variable.
Also, on top of that, I like to add a "Coyote time", and make my on IsGrounded() method, as follows:
public bool IsGrounded()
{
return CoyoteTime < CoyoteTimeMax;
}
public void CoyoteControl()
{
if (CharController.isGrounded)
{
CoyoteTime = 0;
}
else
{
CoyoteTime += Time.deltaTime;
}
}
And then I call the CoyoteControl() on Update(), and I can call IsGrounded() whenever I need.
On the inspector I usually set the CoyoteTimeMax to 0.1 and it makes falls more smooth.
As per you comment. You should not determine if your player is grounded by checking an animation parameter. The best way is to use a RayCast(). So what you have to do:
Create a Layer named Ground, and add all the platforms in your
scene to that layer.
Create a bool variable
i.e
bool isGrounded;
Create a function to check if the character is grounded
Something like:
bool checkGrounded(){
return Physics.Raycast(transform.position, Vector3.down, 2f, 1 << LayerMask.NameToLayer("Ground")));
}
In this answer you can read about the involved parameters in the Raycast
Finally inside the update check if the player is grounded or not
Something like:
void Update(){
isGrounded = checkGrounded();
}
I have found that the isGrounded check can change over the course of the Update() function if you are checking it multiple times. Assigning it to a variable at the beginning of the function may solve the flickering issue.
void Update()
{
bool isGrounded = characterController.isGrounded;
...

making a ball Jump a fixed distance

void Update ()
{
Vector3 input = new Vector3 (0, 0, 1);
Vector3 direction = input.normalized;
Vector3 velocity = direction * speed;
Vector3 moveAmount = velocity * Time.deltaTime;
transform.position += moveAmount;
if(Input.GetKeyDown(KeyCode.Space) && isGrounded)
{
player.AddForce (Vector3.up * jumpForce, ForceMode.Impulse);
}
}
Since Time.deltaTime varies moveAmount also varies for every jump making the distance of the jump vary slightly.
The ball is to jump between blocks separated by a fixed gap and therefore the above behaviour causes problems.
Is there any way I can fix this and make fixed length jumps?
You can use CharacterController for this. Make sure you have a CharacterController and Collider attached to your gameobject. Also if you have a rigibody attached to your game object it may cause it to behave unexpectedly so you might have to contraint it.
public CharacterController controller;
private float verticalVelocity;
private float gravity = 25.0f;
private float jumpForce = 15.0f;
void Awake () {
controller = GetComponent<CharacterController>();
}
void Update () {
if( controller == null )
return;
if( controller.isGrounded)
{
verticalVelocity = -gravity * Time.deltaTime;
if( Input.GetKeyDown(KeyCode.Space) )
{
verticalVelocity = jumpForce;
}
}
else
{
verticalVelocity -= gravity * Time.deltaTime;
}
float moveHorizontal = Input.GetAxis ("Horizontal");
float moveVertical = Input.GetAxis ("Vertical");
Vector3 moveVector = Vector3.zero;
moveVector.x = moveHorizontal * 5.0f;
moveVector.y = verticalVelocity;
moveVector.z = moveVertical * 5.0f;
controller.Move(moveVector * Time.deltaTime);
}
Check this tutorial for reference: https://www.youtube.com/watch?v=miMCu5796KM

Unity3d bunny hopping controller. My velocity decreases when I'm strafing fast

I created a FPS Movement script in unity3d for bunny hopping with references from there, but I have some issues.When I am strafing fast my speed decreases.
I wanted to create something like this
This is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour {
//Strafe Variables
public float gravity = 3f;
public float ground_accelerate = 50f;
public float max_velocity_ground = 4f;
public float air_accelerate = 150f;
public float max_velocity_air = 2f;
public float friction = 8;
bool onGround;
public float jump_force = 5f;
private Vector3 lastFrameVelocity = Vector3.zero;
public Camera camObj;
Rigidbody rb;
Collider coll;
void Start () {
rb = GetComponent<Rigidbody> ();
coll = GetComponent<Collider> ();
}
void Update () {
Vector2 input = new Vector2 (Input.GetAxis ("Horizontal"), Input.GetAxis ("Vertical"));
Vector3 tempVelocity = CalculateFriction(rb.velocity);
tempVelocity += CalculateMovement (input, tempVelocity);
rb.velocity = tempVelocity;
lastFrameVelocity = rb.velocity;
rb.velocity += new Vector3(0f,-gravity,0f) * Time.deltaTime;
}
public Vector3 CalculateFriction(Vector3 currentVelocity)
{
onGround = Grounded();
float speed = currentVelocity.magnitude;
//Code from https://flafla2.github.io/2015/02/14/bunnyhop.html
if (!onGround || Input.GetButton("Jump") || speed == 0f)
return currentVelocity;
float drop = speed * friction * Time.deltaTime;
return currentVelocity * (Mathf.Max(speed - drop, 0f) / speed);
}
//Do movement input here
public Vector3 CalculateMovement(Vector2 input, Vector3 velocity)
{
onGround = Grounded();
//Different acceleration values for ground and air
float curAccel = ground_accelerate;
if (!onGround)
curAccel = air_accelerate;
//Ground speed
float curMaxSpeed = max_velocity_ground;
//Air speed
if (!onGround)
curMaxSpeed = max_velocity_air;
//Get rotation input and make it a vector
Vector3 camRotation = new Vector3(0f, camObj.transform.rotation.eulerAngles.y, 0f);
Vector3 inputVelocity = Quaternion.Euler(camRotation) *
new Vector3(input.x * air_accelerate, 0f, input.y * air_accelerate);
//Ignore vertical component of rotated input
Vector3 alignedInputVelocity = new Vector3(inputVelocity.x, 0f, inputVelocity.z) * Time.deltaTime;
//Get current velocity
Vector3 currentVelocity = new Vector3(velocity.x, 0f, velocity.z);
//How close the current speed to max velocity is (1 = not moving, 0 = at/over max speed)
float max = Mathf.Max(0f, 1 - (currentVelocity.magnitude / curMaxSpeed));
//How perpendicular the input to the current velocity is (0 = 90°)
float velocityDot = Vector3.Dot(currentVelocity, alignedInputVelocity);
//Scale the input to the max speed
Vector3 modifiedVelocity = alignedInputVelocity*max;
//The more perpendicular the input is, the more the input velocity will be applied
Vector3 correctVelocity = Vector3.Lerp(alignedInputVelocity, modifiedVelocity, velocityDot);
//Apply jump
correctVelocity += GetJumpVelocity(velocity.y);
//Return
return correctVelocity;
}
private Vector3 GetJumpVelocity(float yVelocity)
{
Vector3 jumpVelocity = Vector3.zero;
//Calculate jump
if ( Input.GetButton("Jump") && yVelocity < jump_force && Grounded())
{
jumpVelocity = new Vector3(0f, jump_force - yVelocity, 0f);
}
return jumpVelocity;
}
bool Grounded(){
return Physics.Raycast (transform.position, Vector3.down, coll.bounds.extents.y + 0.1f);
}
}

Categories

Resources