Week 3
— GAD170 —
— GAD170 —
Sprinting in games is the movement upgrade to the standard run. While running usually requires a simple push of the analog stick or directional pad to its furthest radius in order to execute, sprinting usually requires an additional button press to initiate. [1]
Implementing a sprint mechanic allows the player to reach destinations quicker by increasing the base movement speed of the Player Controller by a certain amount. We can do this by multiplying the base move speed of the Player Controller with a modifier.
Currently, as seen in Week 2, our Player Controller has its moveSpeed float set to 1f, which is the base speed (as shown in the first panel on the right of this page section). When we add a modifier for the speed, we will multiply the moveSpeed float by the modifier. To implement the modifier, we first have to create two float variables. The first is the speed modifier to multiply with the second variable:
public float sprintSpeedModifier = 2f;
And the second is the variable that the base move speed will be multiplied by:
public float activeSprintModifier = 1f;
Our Player Controller, 'Super Blox Man', moving at the base walking speed. It takes 5.71 seconds to go from left to right.
Super Blox Man moving at the walking speed with the sprint modifier multiplied to it. It takes 2.91 seconds to go from left to right, which is 2.8 seconds faster than walking.
The float of the sprintSpeedModifier doesn't have to be set to 2f—setting the value higher increases the sprint speed. The activeSprintModifier float, however, must stay at 1f so the Player Controller returns to the base walking speed once the sprint key is released; by leaving this float at 1f, the base walking speed will be multiplied by this float and therefore won't change the float of the moveSpeed variable. Also, because these are variables, they must be defined before any events are called (e.g. Void, IEnumerator, etc).
Next step is to define what actually happens if you hold down the sprint key (in this case, the Left Shift key). When using C# in Unity, you can have the script check if an input is activated (AKA if the key is being pressed at that specific frame) before calling anything under it using Unity's Input system. For example, if you use the following function:
if (Input.GetKey(KeyCode.LeftShift) == true)
{
DoThingOne();
}
else
{
DoThingTwo();
}
The script will check if the Left Shift key has been pressed during the frame it is being run in, and if it finds that the Left Shift key is being pressed down, it will call the DoThingOne event. If it finds that the Left Shift key is not being pressed during that frame, it will instead call the DoThingTwo event. Note that the else function is only to be used if there is actually going to be a function/set of functions or event called if the specified key is not pressed. In our case, we will need to use the else function.
For our sprint key to work, we have to tell the script to change the float of the activeSprintModifier variable by making it equal the sprintSpeedModifier whenever the Left Shift key is held down, otherwise set the activeSprintModifier to 1f. We can do this by modifying the snippet of code above to implement this, as such:
if (Input.GetKey(KeyCode.LeftShift) == true)
{
activeSprintModifier = sprintSpeedModifier;
}
else
{
activeSprintModifier = 1f;
}
Note that this must be under the Update event to work, as code placed under Update is called every frame [2]. Now that the Left Shift key has been bound, we can move onto the final step, which is actually having the activeSprintModifier variable affect the base move speed, which is actually pretty simple. If we look at the two lines of code that define what the functions of the W/UpArrow and S/DownArrow are, all we need to do is add activeSprintModifier as an extra multiplication, specifically after currentMoveSpeed, as shown here:
if (Input.GetKey(KeyCode.UpArrow) == true || Input.GetKey(KeyCode.W) == true) { this.transform.position += this.transform.forward * currentMoveSpeed * activeSprintModifier * Time.deltaTime; }
if (Input.GetKey(KeyCode.DownArrow) == true || Input.GetKey(KeyCode.S) == true) { this.transform.position -= this.transform.forward * currentMoveSpeed * activeSprintModifier * Time.deltaTime; }
And now, our Player Controller can sprint. Look at the little athlete go! Godspeed, you magnificent beast.
The method documented above is a method that is both easy to implement, performance-friendly and guaranteed to work just the way you want it. Here's a method I tried before this method that kind of worked, but also didn't.
In this method, I firstly created two variables, just like in the method above, but this time I only created one variable with a float. The first variable was the float which contained the sprint speed:
public float sprintSpeed = 2f;
And the second variable was the sprint speed with buffs received from leveling up, just like with the base move and turn speed:
public float currentSprintSpeed;
To get the buffs from leveling up to work, I did the same thing I did with the move speed, turn speed and jump height—I added 10% of the value of the currentSprintSpeed variable's float to itself. By doing this, the sprint speed would increase by 10% of itself every time the player leveled up.
void SetCurrentSprintSpeed()
{
currentSprintSpeed = this.sprintSpeed + (this.sprintSpeed * 0.1f * level);
Debug.Log("currentSprintSpeed = " + currentSprintSpeed);
}
The problem with this already is that the sprint speed doesn't need any buffs if it's done right. The sprint speed should be a multiple of the base move speed instead of its own stat, and therefore, wouldn't require extra code for increasing the sprint speed each time the Player Controller levels up.
The last step was to get it to work when the Left Shift key was pressed down. This was the two functions I used to bind it up to the Left Shift key to make it work:
if (Input.GetKey(KeyCode.LeftShift) == true && Mathf.Abs(this.GetComponent<Rigidbody>().velocity.y) < 0.01f)
{
currentMoveSpeed = (currentMoveSpeed + currentSprintSpeed);
}
if (Input.GetKey(KeyCode.LeftShift) == false && Mathf.Abs(this.GetComponent<Rigidbody>().velocity.y) < 0.01f)
{
currentMoveSpeed = currentMoveSpeed;
}
So to explain basically, if the Left Shift key is pressed down and the Player Controller is not falling or jumping in the air, the script will increase the move speed of the Player Controller (with the buffs also considered) by adding the currentMoveSpeed value with the currentSprintSpeed value, that being the sprint speed of the Player Controller (with the buffs also considered). One thing about this is the fact that this uses two functions, which actually isn't necessary. The if statement also has a partner statement called 'else', which will be called upon if the criterion for the if statement isn't met. This function can completely replace the second function above and will make your code look cleaner. These two functions were also placed in the Update event, which if you know how Update works, you can probably see where this can go pretty wrong.
As said above in the method that did work, Update is called every frame [2], and it calls and computes/executes whatever is called inside and linked to it (linked to it as in if you are calling another event that is not inside of the Update event). The problem here is what's being executed inside of the Update event. Our currentMoveSpeed value is being manipulated using mathematics, and because it's in the Update event, it will compute those mathematics every frame, therefore increasing the Player Controller's speed every frame, and because of what I set the sprintSpeed float to, it basically gives the Player Controller speed that rivals The Flash.
Starring Super Blox Man as Flash in DC's upcoming entry for their hit series 'The Flash'.
Strafing is the act of moving sideways in a video game, typically either in relation to an enemy or the game's camera. In a third-person video game the camera is positioned behind the player character, facing the direction of their forward movement, and so strafing sideways allows a player to keep the camera focused on something, such as an enemy, while moving in a different direction. [3]
A strafing mechanic is essential for modern games that use a movement system as it makes the movement easier and smoother. Having a movement system that only allows you to walk forward, backwards, and turn left and right is very clunky.
[1] Giantbomb. [n.d.]. Sprinting (Concept). Retrieved February 23, 2022 from https://www.giantbomb.com/sprinting/3015-603/
[2] Unity. [2020]. MonoBehaviour.Update(). Retrieved February 26th, 2022 from https://docs.unity3d.com/ScriptReference/MonoBehaviour.Update.html
[3] Ultimate Pop Culture Wiki. [n.d.]. Strafing (video games). Retrieved February 26, 2022 from https://ultimatepopculture.fandom.com/wiki/Strafing_(video_games)