- Home /
Crawl, Walk and Sprint movement speeds
This should be straightforward, or so I thought. Getting quite late so probably just tiredness dumbing me down. I could use a fresh set of eyes on this.
In our game the player character needs to be able to move at different speeds depending on the keys held down. By default, the PC will move at the walkSpeed, and with "c" held down will slow to a crawl, while with "left shift" held down will accelerate to his top sprinting speed. I'd also like to include stamina, so that after a few seconds at top speed, the PC slows back to walking speed and must wait for a cool down period before being able to sprint again.
Here's my script so far. It's a modified version of the FPSWalker script For some reason, holding shift only increases the speed by 1, and not continuously until the limit as i'd like, despite using Input.GetButton to do it as long as the key is held down. Changing speeds worked with hardcoded values, but we'd like to have speeds in multiples like this so it's easier to scale. Also the sprint stamina timer doesn't seem to be having an effect.
var currentSpeed : float; var walkSpeed : float = 6.0; var maxSpeed : float = 15.0;
var sprintStamina : float = 8.0; var sprintTimer : float = 0.0; var isCoolingDown : boolean = false;
var rotateSpeed : float = 100.0;
var jumpSpeed : float = 8.0;
// artificial gravity since we are not using a rigidbody var gravity = 20.0;
// variable to store the player's current forward direction private var moveDirection = Vector3.zero;
// boolean variable to track whether the player is on the ground private var grounded : boolean = false; static var allowMove : boolean = true; static var playerSneaking : boolean = false;
function Update(){
if(!Input.GetButton("Crouch") && !Input.GetButton("Run")){
currentSpeed = walkSpeed;
}
if (Input.GetButton("Crouch")) {
// load the game
currentSpeed = walkSpeed * 0.5;
playerSneaking = true;
// print("SNEAKING at "+walkSpeed);
}
if (Input.GetButton("Run")){
if(!isCoolingDown){
if (currentSpeed <= maxSpeed){
currentSpeed++;
// print("running");
} else {
sprintControl();
}
}
}
}
// fixed update function is called every fixed framerate frame // so is more accurate for physics stuff function FixedUpdate() {
if(allowMove){
if (grounded) {
// We are grounded, so store a new heading vector based on up/down key inputs
moveDirection = new Vector3(0, 0, Input.GetAxis("Vertical"));
// convert local xyz co-ordinates above to world co-ordinates
moveDirection = transform.TransformDirection(moveDirection);
// multiply by speed value (editable in the editor)
moveDirection *= currentSpeed;
// rotate around the y axis at the rotation speed per second
transform.Rotate(0,Input.GetAxis("Horizontal") * rotateSpeed * Time.deltaTime, 0);
// If the default jump button is pressed (spacebar)
// set the y property of the players heading to the jumpSpeed value
if (Input.GetButton ("Jump")) {
moveDirection.y = jumpSpeed;
}
}
// Subtract the value of gravity once a second to bring the player back down
moveDirection.y -= gravity * Time.deltaTime;
// Move the controller
// store a reference to the CharacterController component of this object in a variable called 'controller'
var controller : CharacterController = GetComponent(CharacterController);
// move the controller along the heading specified by moveDirection and in metres per second (store this movement in a variable called 'flags')
var flags = controller.Move(moveDirection * Time.deltaTime);
// set the grounded variable to the result returned by the comparison between
// the collisions in the variable flags and the internal CollidedBelow collision flag
// of the character controller. If there is a collision, the value returned will be
// 1 or 'not zero' as is set here when we are colliding.
grounded = (flags & CollisionFlags.CollidedBelow) != 0;
}
}
function sprintControl(){ sprintTimer += Time.deltaTime; if(sprintTimer > sprintStamina){ currentSpeed = walkSpeed; isCoolingDown = true; yield WaitForSeconds(3.0); isCoolingDown = false; sprintTimer = 0.0; } }
// this line makes sure that a character controller is always assigned to the object this script is attached to. @script RequireComponent(CharacterController)
Answer by Mike 3 · May 19, 2010 at 02:50 AM
The problem with the above code is that you're setting currentSpeed at the top of Update, so each time you increase it, next time it's walk speed again
I would set it to that only if crouch and run is not held - also, you should probably set the crouch speed to walkSpeed *0.5 instead of currentSpeed *0.5, otherwise you may get odd speeds when runcrouching
Hi $$anonymous$$ike, thanks for that. I knew it would be something obvious - i've actually just now been implementing something else and had to add an if statement to stop overriding the speed in Update() so I should've realised. It seems to be working now except it never seems to reach the maxSpeed of 15, it gets to 13. Any reason why that would be? I've amended my code above with your suggestions.
Can't really see any bugs there straight off - i would check that the values are set right in the inspector (i.e. it's set to 15, not 13 there) and check it's not hitting the cooldown
Your answer
![](https://koobas.hobune.stream/wayback/20220613005816im_/https://answers.unity.com/themes/thub/images/avi.jpg)