- Home /
How to apply smooth damp to movement?
Hi, my current movement when rapidly pressing left, right, forward, backward feels too snappy. How do I make it so that the speed builds up to its full potential speed, when you hold the button long enough? I'm a beginner, so could you explain why and how it would work?
Here's my code:
public class CharacterMovement : MonoBehaviour {
public CharacterController controller;
public Transform cam;
public float speed = 6f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");
Vector3 direction = new Vector3(horizontal, 0, vertical).normalized;
if (direction.magnitude >= 0.1f)
{
float targetAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg + cam.eulerAngles.y;
Vector3 moveDirection = Quaternion.Euler(0f, targetAngle, 0f) * Vector3.forward;
controller.Move(moveDirection.normalized * speed * Time.deltaTime);
}
}
Answer by Pangamini · Jul 13, 2021 at 11:51 PM
Create a speed or velocity member variable and increase / decrease that when you press the button. For example
float speed; // make this a member of the class
float forwardInput = keyPressed? 1 : 0;
speed = Mathf.MoveTowards(speed, forwardInput * walkSpeed, Time.deltaTime * acceleration);
Make sure it's the class member variable, not a local variable, so its value is preserved. Then, simply move the character by the speed / velocity in every Update
position += Transform.forward * speed * Time.deltaTime;
Extend this code to add negative speed when backwards button is pressed (or add strafing as well) The difference between the speed and velocity could be that speed is a scalar while velocity is a vector. In the example above, you accumulate speed that you move forward with, even after your character changes facing (rotates / turns). You could hold a velocity variable instead of a speed, expressing the movement over time in world space. In such case it could look like this
Vector3 velocity; //again, a member of the class
float forwardInput = keyPressed? 1 : 0;
velocity = Vector3.MoveTowards(velocity, Transform.forward * forwardInput * walkSpeed, Time.deltaTime * acceleration);
position += velocity * Time.deltaTime;
The difference here is that once you accumulate velocity, you will continue moving in that same direction even after your character turns / rotates
I'm having trouble understanding. There is a problem with keyPressed, is it a function? Should I have "speed = Mathf.MoveTowards(speed, forwardInput walkSpeed, Time.deltaTime acceleration);" as the body of that function?
Here's my current Code: public class CharacterMovement : MonoBehaviour {
public CharacterController controller;
public Transform cam;
//public float speed = 6f;
float speed;
public float walkSpeed = 100f;
public float acceleration = 100f;
// Update is called once per frame
void Update()
{
float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");
Vector3 direction = new Vector3(horizontal, 0, vertical).normalized;
float forwardInput = keyPressed ? 1 : 0;
speed = Mathf.MoveTowards(speed, forwardInput * walkSpeed, Time.deltaTime * acceleration);
if (direction.magnitude >= 0.1f)
{
float targetAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg + cam.eulerAngles.y;
Vector3 moveDirection = Quaternion.Euler(0f, targetAngle, 0f) * Vector3.forward;
controller.Move(moveDirection.normalized * speed * Time.deltaTime);
}
}
}
Consider it a pseudocode. Replace keyPressed with your input method - GetAxisRaw
There's another problem for whatever reason. "W" works fine for moving forward, however, "S" also makes the player move forward. Sometimes both inputs have problem where the player will move back and then move forward again. The strafe buttons don't work unless I'm using them with the forward or back input, resulting in moving diagonally, so at least moving diagonally works. I added some other functions while trying to fix things, but I don't think they interfere with the movement code. Thanks for helping, I really appreciate it.
Here's the Code: using System.Collections; using System.Collections.Generic; using UnityEngine;
public class CharacterMovement : MonoBehaviour {
public CharacterController controller;
public Transform cam;
public float speed;
public float walkSpeed = 100f;
public float acceleration = 10f;
public float gravity = -9.81f;
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;
Vector3 velocity;
bool isGrounded;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
CalculateGravity();
CalculateGrounded();
CalculateMovement();
}
private void CalculateMovement()
{
float strafeInput = Input.GetAxisRaw("Horizontal");
float forwardInput = Input.GetAxisRaw("Vertical");
//float horizontal = Input.GetAxisRaw("Horizontal");
//float vertical = Input.GetAxisRaw("Vertical");
Vector3 direction = new Vector3(strafeInput, 0, forwardInput).normalized;
speed = Mathf.MoveTowards(speed, forwardInput * walkSpeed, Time.deltaTime * acceleration);
if (direction.magnitude >= 0.1f)
{
float targetAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg + cam.eulerAngles.y;
Vector3 moveDirection = Quaternion.Euler(0f, targetAngle, 0f) * Vector3.forward;
controller.Move(moveDirection.normalized * speed * Time.deltaTime);
}
}
private void CalculateGravity()
{
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
private void CalculateGrounded()
{
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
if(isGrounded && velocity.y < 0)
{
velocity.y = -2f;
}
}
Your answer
Follow this Question
Related Questions
The name 'Joystick' does not denote a valid type ('not found') 2 Answers
NPC jittery/stuttery Movement 2 Answers
Making a bubble level (not a game but work tool) 1 Answer
Camera Movement 1 Answer