0
votes

I have been trying to properly limit movement on my 3D fps controller, and I have so far just been using basic clamping to limit the speed on the X and Z axis. The problem with this is that any external forces will never cause the player to exceed its predefined maximum speed, meaning that external forces like explosions do basically nothing to move the player like an explosion should. My idea for getting this to work was to only allow additional movement input if the player was below a certain maximum velocity, but so far I have been unable to get it to work in code. I am fairly new to working in 3D space with vectors, so I am pretty lost on what to do. My attempted implementation worked until the player turned their head while moving, at which point the movement would not be limited. Here is the code I have tried:

xInput = Input.GetAxisRaw("Horizontal");
yInput = Input.GetAxisRaw("Vertical");
    
if (xInput > 0 && transform.InverseTransformDirection(rb.velocity).x > inputMaximumSpeed) xInput = 0;
if (xInput < 0 && transform.InverseTransformDirection(rb.velocity).x > -inputMaximumSpeed) xInput = 0;
if (yInput > 0 && transform.InverseTransformDirection(rb.velocity).z > inputMaximumSpeed) yInput = 0;
if (yInput < 0 && transform.InverseTransformDirection(rb.velocity).z > -inputMaximumSpeed) yInput = 0;
    
//Apply Movement
moveDirection = (xInput * transform.right + yInput * transform.forward).normalized;
rb.AddForce(moveDirection * groundAccSpeed);

Not too sure what to do to fix this, as I have found little to none in terms of examples on how others have gotten this to work. Thanks for any help!

1

1 Answers

0
votes

For the negative input parts shouldn't it be e.g.

//  |
//  v
... < -inputMaximumSpeed

since you only want to clamp if the velocity is too small and the input negative.

I think another issue is: You normalize the input always. So even if the Input is very small (or zero) you scale it up to 1. You might rather like to only normalize if the magnitude is greater than 1.

I would also recommend to rather use AddRelativeForce

xInput = Input.GetAxisRaw("Horizontal");
yInput = Input.GetAxisRaw("Vertical");

// Rather store this only once
var relativeVelocity = transform.InverseTransformDirection(rb.velocity);

if (xInput > 0 && relativeVelocity.x > inputMaximumSpeed) xInput = 0;
// rather use else if since the conditions are exclusive
else if (xInput < 0 && relativeVelocity.x < -inputMaximumSpeed) xInput = 0;

if (yInput > 0 && relativeVelocity.z > inputMaximumSpeed) yInput = 0;
else if (yInput < 0 && relativeVelocity.z < -inputMaximumSpeed) yInput = 0;
    
// create a relative vector
moveDirection = new Vector3 (xInput, 0, yInput);
// Normalize only if magnitude exceeds 1
if(moveDirection.sqrMagnitude > 1f) moveDirection.Normalize();
// add the force relative
rb.AddRelativeForce(moveDirection * groundAccSpeed);