Creating abilities - Ground pound
Eduardo Julião
Posted on August 11, 2023
Cool! Our character can move left, right and jump! (and fall off the edge of the map 😅).
But we can add something to our character to make our jump more, spicy, what about we add a Ground pound option?
It's pretty simple and can open a lot of doors for movement interaction, such as breakable ground and force push enemies once we hit the ground.
Also, it's not needed to create a new binding action in our PlayerInput
script, we're going to use what we've already created and check for 3 things, if the player is holding down on the controller (or S or down arrow key) pressed jump and it's not grounded.
Ground Pound code
New fields
Let's start by creating something similar to jumpForce
, but instead of making our character go up, we'll make our character go down.
And since we've added a Boolean
field to tell us if the player pressed the jump button while grounded, we're going to use the same principle and create a field to tell us if the player met the conditions to do a ground pound
.
And a couple more fields to help us, such as verticalMovement
( which follows the same idea of horizontal movement, but for, well, vertical) and baseGravityScale
, which is the default gravity value our RigidBody2D
starts with (in our scenario, 1).
And finally, set our baseGravityScale
in the Awake
method.
Updating our new fields
Let's starting by updating our verticalMovement
by reading the Y
value from our input.
With our verticalMovement
updating, we can do our check.
Updating FixedUpdate
method
Now, it's time to use these new fields in our FixedUpdate
method, which controls the character.
First, let's update our velocityX
variable, because we don't want to our player to move while ground pound is active.
To do that, we check if isForceDown
is true, if it's true, we set our X movement to 0, otherwise, we keep the same movement logic as before.
And if it's force down, we set our gravityScale
in the RigidBody
to our downforce
.
Some other code changes
Since we're creating more and more fields, I've decided to handle them in a single if
statement instead of handling them individually.
In here, I'm setting isForceDown
and hasJumpButtonTriggered
back to false, and body.gravityScale
back to its default.
Now that we have a single if
statement to handle these fields, we can remove hasJumpButtonTriggered = false
from our hasJumpButtonTriggered
check, making the code simply:
Important changes
In some occasions, we're falling to fast to Unity to detect collision, this will break and make the player fall through the ground, to fix that, change the Collision Detection
from Discrete
to Continuous
in the RigidBody2D options.
Thanks
And that's pretty much it! There's a lot of room for improvements but, its taking shape, slowly but surely! Hope this series is helpful, fun and easy to read! Until next chapter!
Full code
public class PlayerMovement : MonoBehaviour
{
private PlayerInput playerInput;
private Rigidbody2D body;
private float horizontalMovement;
private float verticalMovement;
private float baseGravityScale;
private bool hasJumpButtonTriggered;
private bool isForceDown;
[SerializeField]
private float speed = 5f;
[SerializeField]
private float jumpForce = 5f;
[SerializeField]
private float downForce = 5f;
[SerializeField]
private bool isGrounded;
[SerializeField]
private Transform groundCheck;
[SerializeField]
private LayerMask groundLayer;
private void Awake()
{
playerInput = new PlayerInput();
body = GetComponent<Rigidbody2D>();
baseGravityScale = body.gravityScale;
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
horizontalMovement = Mathf.RoundToInt(playerInput.Player.Move.ReadValue<Vector2>().x);
verticalMovement = Mathf.RoundToInt(playerInput.Player.Move.ReadValue<Vector2>().y);
isGrounded = Physics2D.OverlapCircle(groundCheck.position, 0.02f, groundLayer);
if(playerInput.Player.Jump.triggered && isGrounded)
hasJumpButtonTriggered = true;
if (playerInput.Player.Jump.triggered && verticalMovement == -1 && !isGrounded)
isForceDown = true;
}
private void FixedUpdate()
{
var velocityX = !isForceDown ? speed * horizontalMovement : 0;
body.velocity = new Vector2(velocityX, body.velocity.y);
if (hasJumpButtonTriggered)
{
body.velocity = new Vector2(body.velocity.x, jumpForce);
}
if (isForceDown)
body.gravityScale = downForce;
if (isGrounded)
{
isForceDown = false;
hasJumpButtonTriggered = false;
body.gravityScale = baseGravityScale;
}
}
private void OnEnable()
{
playerInput.Player.Enable();
}
private void OnDisable()
{
playerInput.Player.Disable();
}
}
Posted on August 11, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.