So, i have completed a tutorial series about a 2D platformer controller.
I edited it a bit, because some multiplier caused me a lot of bug, and chunky movement.
The movement is almost perfect for my game’s style, but there are a thing.
When i try to move in the mid air, the character only move when it has a starting speed in the ground.
so when i just jump, and then try to move i cant, but if i run and jump, i can move to the other direction.
here it is what i did:
{
private float movementInputDirection;
private float fJumpPressedRemember = 0;
private float fJumpPressedRememberTime = 0.2f;
private float fGroundedRemember = 0;
private float fGroundedRememberTime = 0.2f;
private int amountOfJumpsLeft;
private int facingDirection = 1;
private bool isFacingRight = true;
private bool isWalking;
private bool isGrounded;
private bool isTouchingWall;
private bool isWallSliding;
private bool canJump;
private Rigidbody2D rb;
private Animator anim;
public int amountOfJumps = 1;
public float movementSpeed = 10.0f;
public float jumpForce = 16.0f;
public float groundCheckRadius;
public float wallCheckDistance;
public float wallSlideSpeed;
public float moveForceInAir;
//public float airDragMultiplier = 0.95f;
//public float variableJumpHeightMultiplier = 0f;
public float wallHopForce;
public float wallJumpForce;
public Vector2 wallHopDirection;
public Vector2 wallJumpDirection;
public Transform groundCheck;
public Transform wallCheck;
public LayerMask whatIsGround;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
amountOfJumpsLeft = amountOfJumps;
wallHopDirection.Normalize();
wallJumpDirection.Normalize();
}
// Update is called once per frame
void Update()
{
CheckInput();
CheckMovementDirection();
UpdateAnimations();
CheckIfCanJump();
CheckIfWallSliding();
}
private void FixedUpdate()
{
ApplyMovement();
CheckSurroundings();
}
private void CheckIfWallSliding()
{
if (isTouchingWall && !isGrounded && rb.velocity.y < 0)
{
isWallSliding = true;
}
else
{
isWallSliding = false;
}
}
private void CheckSurroundings()
{
isGrounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, whatIsGround);
isTouchingWall = Physics2D.Raycast(wallCheck.position, transform.right, wallCheckDistance, whatIsGround);
}
private void UpdateAnimations()
{
anim.SetBool("isWalking", isWalking);
anim.SetBool("isGrounded", isGrounded);
anim.SetFloat("yVelocity", rb.velocity.y);
anim.SetBool("isWallSliding", isWallSliding);
}
private void CheckIfCanJump()
{
if ((isGrounded && rb.velocity.y <= 0) || isWallSliding)
{
amountOfJumpsLeft = amountOfJumps;
}
if (amountOfJumpsLeft <= 0)
{
canJump = false;
}
else
{
canJump = true;
}
}
private void CheckMovementDirection() //Karakter direction-t lekérdezi
{
if(isFacingRight && movementInputDirection < 0)
{
Flip();
}
else if(!isFacingRight && movementInputDirection > 0)
{
Flip();
}
if(rb.velocity.x != 0)
{
isWalking = true;
}
else
{
isWalking = false;
}
}
private void CheckInput() //Inputok
{
movementInputDirection = Input.GetAxisRaw("Horizontal");
fJumpPressedRemember -= Time.deltaTime;
if (Input.GetButtonDown("Jump"))
{
fJumpPressedRemember = fJumpPressedRememberTime;
Jump();
}
fGroundedRemember -= Time.deltaTime;
if (isGrounded)
{
fGroundedRemember = fGroundedRememberTime;
}
//if (Input.GetButtonUp("Jump"))
//{
//rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y * variableJumpHeightMultiplier);
//}
}
private void Jump()
{
if (canJump && !isWallSliding && (fJumpPressedRemember > 0) && (fGroundedRemember > 0))
{
fGroundedRemember = 0;
fJumpPressedRemember = 0;
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
amountOfJumpsLeft--;
}
else if (isWallSliding && movementInputDirection == 0 && canJump) //wall hop
{
isWallSliding = false;
amountOfJumpsLeft--;
Vector2 forceToAdd = new Vector2(wallHopForce * wallHopDirection.x * -facingDirection, wallHopForce * wallHopDirection.y);
rb.AddForce(forceToAdd, ForceMode2D.Impulse);
}
else if ((isWallSliding || isTouchingWall)&& movementInputDirection != 0 && canJump)
{
isWallSliding = false;
amountOfJumpsLeft--;
Vector2 forceToAdd = new Vector2(wallJumpForce * wallJumpDirection.x * movementInputDirection, wallJumpForce * wallJumpDirection.y);
rb.AddForce(forceToAdd, ForceMode2D.Impulse);
}
}
private void ApplyMovement()
{
if (isGrounded)
{
rb.velocity = new Vector2(movementSpeed * movementInputDirection, rb.velocity.y);
}
else if (!isGrounded && !isWallSliding && movementInputDirection != 0)
{
Vector2 forceToAdd = new Vector2(moveForceInAir * movementInputDirection, 0);
rb.AddForce(forceToAdd);
if (Mathf.Abs(rb.velocity.x) > movementSpeed)
{
rb.velocity = new Vector2(movementSpeed * movementInputDirection, rb.velocity.y);
}
}
else if (!isGrounded && !isWallSliding && movementInputDirection == 0)
{
//rb.velocity = new Vector2(rb.velocity.x * airDragMultiplier, rb.velocity.y);
rb.velocity = new Vector2(rb.velocity.x * moveForceInAir, rb.velocity.y);
}
if (isWallSliding)
{
if(rb.velocity.y < -wallSlideSpeed)
{
rb.velocity = new Vector2(rb.velocity.x, -wallSlideSpeed);
}
}
}
private void Flip()
{
if (!isWallSliding)
{
facingDirection *= -1;
isFacingRight = !isFacingRight;
transform.Rotate(0.0f, 180.0f, 0.0f);
}
}
private void OnDrawGizmos()
{
Gizmos.DrawWireSphere(groundCheck.position, groundCheckRadius);
Gizmos.DrawLine(wallCheck.position , new Vector3(wallCheck.position.x + wallCheckDistance, wallCheck.position.y, wallCheck.position.z));
}
}