Home > database >  How do I implement momentum for a ball that moves based on directional movement input?
How do I implement momentum for a ball that moves based on directional movement input?

Time:10-23

How can I make my ball roll a little bit further after I release the w,a,s,d keys (directional movement keys)? Currently, if I stop pressing w,a,s,d, the ball just stops moving immediately, but I'd like it to have momentum and keep rolling a bit after I release the keys.

Here is what I've written so far:

public float speed = 6f;

public float turnSmoothTime = 0.1f;
float turnSmoothVelocity;


// Update is called once per frame
void Update()
{
    float horizontal = Input.GetAxisRaw("Horizontal");
    float vertical = Input.GetAxisRaw("Vertical");
    Vector3 direction = new Vector3(horizontal, 0f, vertical).normalized;

    if(direction.magnitude >= 0.1f)
    {
        float targetAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg   cam.eulerAngles.y;
        float angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime);
        transform.rotation = Quaternion.Euler(0f, angle, 0f);

        Vector3 moveDir = Quaternion.Euler(0f, targetAngle, 0f) * Vector3.forward;
        controller.Move(moveDir.normalized * speed * Time.deltaTime);

    }
}

CodePudding user response:

Basically add physics and momentum. A key press equalizer expertise force/transfer energy (E=0.5mv^2 ro get the speed) Every update a fractioneel force is applied (see wiki, constant v^3 if I remember correct)

Result is a ball that gradually gains speed, granulaat slows down and does not change direction immediatly. Make the friction big compared to the force to make controle snappen.

CodePudding user response:

The best approach would be to use a rigidbody to intereact with the physics engine (the effect you are looking for would be easier achieved this way). However, if you rather use a character controller then I suggest first creating a method to execute your input (example / psuedocode):

void MovePlayer(moveDir) {
 
    // Your moving logic
}

Next, you could create a timer that automatically calls this method for an 'x' amount of time after your input is stopped (example / psuedocode):

float rollTimer = 0;

void Update() {

    float horizontal = Input.GetAxisRaw("Horizontal");
    float vertical = Input.GetAxisRaw("Vertical");

    // Add your logic to calculate when to activate the rolling effect
    // possibly a toggle based on your horizontal & vertical input
    timer = (horizontal != 0 && vertical != 0) ? 0 : 3;
    
    // Add an if statement, so that you arent constantly setting timer to 0
    if(timer > 0) {

         while(timer > 0) {
            
             MovePlayer(/* Simulated input */);
             rollTimer -= time.deltaTime;
         }

         // Reset the timer
         rollTimer = 0;
    }        
}

I can not test this right now, so you may have to tweak it more to fit your exact code, but the concept remains true. This is the simpliest logic I could think of that doesn't use a rigidbody. If you decide to switch to a rigidbody approach, then you can just use the AddForce() method which can give the same effect with natural looking results from the physics engine.

  • Related