简体   繁体   中英

Not clamping the Y Velocity in AddForce?

I'm making a character move right with addforce and in order to keep the player from infinitely going up to mach 10, I clamp the velocity. Which works fine HOWEVER if I clamp the velocity it also clamps the y velocity which prevents me from jumping.

Gif of Problem

if (moveDir.magnitude >= 0.1f)
        {
            controller.AddForce(moveDir * moveSpeed, ForceMode.Impulse);
            //Needs a fix because it also clamps the Y velocity which is needed so it doesn't fall slowly

            controller.velocity = Vector3.ClampMagnitude(controller.velocity, moveSpeed);
            //Animation Call
            animationCaller.Animation_Move(animator);
        }
        else
        {
            //Needs a fix because it also clamps the Y velocity which is needed so it doesn't fall slowly
            controller.velocity = Vector3.ClampMagnitude(controller.velocity, 0f);
            controller.angularVelocity = Vector3.ClampMagnitude(controller.angularVelocity, 0f);
            //Animation Call
            animationCaller.Animation_Idle(animator);
        }

Tried seperating them all into their own vector 3 and then re adding back the y velocity after it calmps it but that causes an issue where the velocity never goes back down.

controller.AddForce(moveDir * moveSpeed, ForceMode.Impulse);

            /*
            Vector3 clampVelocity;
            clampVelocity.x = 0;
            clampVelocity.y = controller.velocity.y;
            clampVelocity.z = 0;
            */

            controller.velocity = Vector3.ClampMagnitude(controller.velocity, moveSpeed); // + clampVelocity;

When you clamp the magnitude of a Vector, you limit its scalar size. That means, irrespective of direction it can't exceed a given size.

If you want to impose a limit to the non-vertical components, you can project the Z and X components onto a 2D vector, and clamp that, then, set the X and Z components on the original Vector3 accordingly.

To make this behavior well integrated, it would be wise to add assignment logic to a property for the velocity vector. However, this may require you to extend the physics object class you're using. Since you call the velocity member of the GameObject itself (which is just a redirect to the velocity of the first physics component it finds) you can either change the type of the physics controller you're assigning, or hide the inherited velocity properly of your gameObject.

I think your were close but you want to first clamp only XZ and then keep the current Y velocity like eg

controller.AddForce(moveDir * moveSpeed, ForceMode.Impulse);

// get velocity
var currentVelocity = controller.velocity;
// store Y axis
var currentY = currentVelocity.y;
// reset Y axis - so it doesn't influence the clamp
currentVelocity.y = 0;
// clamp magnitude of XZ
currentVelocity = Vector3.ClampMagnitude(currentVelocity, moveSpeed);
// re-apply Y axis
currentVelocity.y = controller.velocity.y;
        
controller.velocity = currentVelocity;

Though my question would be why even use AddForce at all?

You could probably as well just compose the velocity directly like

// already clamp on the input 
var velocity = Vector3.ClampMagnitude(moveDir * moveSpeed);
// also take over current Y axis
velocity.y = controller.velocity.y;
        
controller.velocity = velocity;

Then what exactly is

controller.velocity = Vector3.ClampMagnitude(controller.velocity, 0f);

supposed to do? If you clamp the magnitude to 0 you can as well just right Vector3.zero . If you only want to reset two components XZ you could simply do

var velocity = controller.velocity;
velocity.x = 0;
velocity.z = 0;
controller.velocity = velocity;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM