I'm making a 2D game in Unity 2D, and all is going pretty well. But I problem that I'm having is that, when the player is wall sliding, the bool, IsWallSliding keeps turning to true and false.
Here Is a video of this happening with some other things that might have caused it: https://www.youtube.com/watch?v=2TwrrSAG-sI
Here is my character controller:
using System.Collections;
using UnityEngine;
using UnityEngine.Events;
public class CharacterController2D : MonoBehaviour
{
[SerializeField] private float m_JumpForce = 400f;
[Range(0, .3f)] [SerializeField] private float m_MovementSmoothing = .05f;
[SerializeField] private bool m_AirControl = true;
[SerializeField] private LayerMask m_WhatIsGround;
[SerializeField] private Transform m_GroundCheck;
[SerializeField] private Transform m_CeilingCheck;
const float k_GroundedRadius = .2f;
public bool m_Grounded;
private Rigidbody2D m_Rigidbody2D;
public bool m_FacingRight = true;
private Vector3 m_Velocity = Vector3.zero;
public LayerMask Wall;
public Animator animator;
[Header("Events")]
[Space]
public UnityEvent OnLandEvent;
[System.Serializable]
public class BoolEvent : UnityEvent<bool> { }
private void Awake()
{
m_Rigidbody2D = GetComponent<Rigidbody2D>();
if (OnLandEvent == null)
OnLandEvent = new UnityEvent();
}
private void FixedUpdate()
{
bool wasGrounded = m_Grounded;
m_Grounded = false;
designated as ground
Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position, k_GroundedRadius, m_WhatIsGround);
for (int i = 0; i < colliders.Length; i++)
{
if (colliders[i].gameObject != gameObject)
{
m_Grounded = true;
if (!wasGrounded)
OnLandEvent.Invoke();
}
}
gameObject.GetComponent<PlayerMovement>().animator.SetBool("IsJumping", !m_Grounded);
}
private void Update()
{
Debug.DrawRay(transform.position, transform.TransformDirection(Vector2.down) * 0.51f, Color.red);
RaycastHit2D groundedOnWall = Physics2D.Raycast(transform.position, transform.TransformDirection(Vector2.down), 0.51f, Wall);
if(groundedOnWall)
{
Debug.Log("Grounded on Wall");
animator.SetBool("IsJumping", false);
m_Grounded = true;
}
}
public void Move(float move, bool jump)
{
if (m_Grounded || m_AirControl)
{
Vector3 targetVelocity = new Vector2(move * 10f, m_Rigidbody2D.velocity.y);
m_Rigidbody2D.velocity = Vector3.SmoothDamp(m_Rigidbody2D.velocity, targetVelocity, ref m_Velocity, m_MovementSmoothing);
if (move > 0 && !m_FacingRight)
{
Flip();
}
else if (move < 0 && m_FacingRight)
{
Flip();
}
}
if (m_Grounded && jump)
{
m_Grounded = false;
m_Rigidbody2D.AddForce(new Vector2(0f, m_JumpForce));
}
}
public void Flip()
{
if (!gameObject.GetComponent<PlayerMovement>().isWallSliding)
{
gameObject.GetComponent<PlayerMovement>().wallJumpDirection *= -1;
m_FacingRight = !m_FacingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
}
With the charcater controller script, I also have this player movement script:
using System.Collections;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[Header("Wall Sliding")]
[SerializeField] private float wallSlideSpeed = 0f;
[SerializeField] private LayerMask wallLayer;
[SerializeField] private Transform wallCheckPoint;
[SerializeField] private Vector2 wallCheckSize;
private bool isTouchingWall;
public bool isWallSliding;
private const float wallCheckRadius = 0.2f;
[Header("Wall Jumping")]
[SerializeField] private float wallJumpForce = 18f;
[SerializeField] public float wallJumpDirection = -1f;
[SerializeField] private Vector2 wallJumpAngle;
[Header("Player Components")]
[SerializeField] private CharacterController2D controller;
[SerializeField] public Animator animator;
[SerializeField] private Rigidbody2D rb;
[SerializeField] private GameObject wallCheck;
[SerializeField] private BoxCollider2D regularBoxColl;
[SerializeField] private CircleCollider2D regularCircleColl;
[SerializeField] private BoxCollider2D slideColl;
[Header("Running & Jumping")]
[SerializeField] private float runSpeed = 40f;
[SerializeField] private float horizontalMove = 0f;
[SerializeField] private bool jump = false;
[Header("Sliding")]
[SerializeField] private float slideSpeed = 5f;
[SerializeField] private bool isSliding = false;
private void Start()
{
wallJumpAngle.Normalize();
}
void Update()
{
WorldCheck();
WallSlide();
WallJump();
horizontalMove = Input.GetAxisRaw("Horizontal") * runSpeed;
animator.SetFloat("Speed", Mathf.Abs(horizontalMove));
if (controller.m_Grounded && animator.GetBool("IsJumping"))
{
animator.SetBool("IsJumping", false);
}
if (!animator.GetBool("IsSliding") && Input.GetButtonDown("Jump"))
{
animator.SetBool("IsJumping", true);
jump = true;
}
else if(controller.m_Grounded)
{
animator.SetBool("IsJumping", false);
}
if (!animator.GetBool("IsJumping") && Input.GetKeyDown(KeyCode.LeftShift))
{
PreformSlide();
}
if(Input.GetButtonDown("Jump") && animator.GetBool("IsSliding") && !controller.m_Grounded)
{
animator.SetBool("IsJumping", true);
animator.SetBool("IsSliding", false);
}
animator.SetFloat("yVelocity", rb.velocity.y);
if(isWallSliding && animator.GetBool("IsJumping"))
{
animator.SetBool("IsJumping", false);
animator.SetBool("IsWallSliding", true);
}
}
void FixedUpdate()
{
controller.Move(horizontalMove * Time.fixedDeltaTime, jump);
jump = false;
}
private void PreformSlide()
{
isSliding = true;
animator.SetBool("IsSliding", true);
regularBoxColl.enabled = false;
regularCircleColl.enabled = false;
slideColl.enabled = true;
if (!controller.m_FacingRight)
{
rb.AddForce(Vector2.right * slideSpeed);
}
else
{
rb.AddForce(Vector2.left * slideSpeed);
}
if(Input.GetButtonDown("Jump") && isSliding)
{
animator.SetBool("IsSliding", false);
regularBoxColl.enabled = true;
regularCircleColl.enabled = true;
slideColl.enabled = false;
isSliding = false;
}
StartCoroutine("StopSlide");
}
IEnumerator StopSlide()
{
yield return new WaitForSeconds(0.75f);
animator.SetBool("IsSliding", false);
regularBoxColl.enabled = true;
regularCircleColl.enabled = true;
slideColl.enabled = false;
isSliding = false;
}
private void WorldCheck()
{
isTouchingWall = Physics2D.OverlapBox(wallCheckPoint.position, wallCheckSize, 0, wallLayer);
}
private void WallSlide()
{
if (isTouchingWall && !controller.m_Grounded && rb.velocity.y < 0)
{
animator.SetBool("IsWallSliding", true);
isWallSliding = true;
}
else
{
animator.SetBool("IsWallSliding", false);
isWallSliding = false;
}
if (isWallSliding)
{
rb.velocity = new Vector2(rb.velocity.x, wallSlideSpeed);
}
}
private void WallJump()
{
if (isWallSliding && isTouchingWall && Input.GetButtonDown("Jump"))
{
rb.AddForce(new Vector2(wallJumpForce * wallJumpDirection * wallJumpAngle.x, wallJumpForce * wallJumpAngle.y), ForceMode2D.Impulse);
animator.SetBool("IsWallSliding", false);
animator.SetBool("IsJumping", false);
animator.SetBool("IsWallJumping", true);
controller.Flip();
StartCoroutine(EndWallJump());
}
}
IEnumerator EndWallJump()
{
yield return new WaitForSeconds(0.1f);
animator.SetBool("IsWallJumping", false);
}
public void OnLanding()
{
animator.SetBool("IsJumping", false);
}
private void OnDrawGizmosSelected()
{
Gizmos.color = Color.blue;
Gizmos.DrawCube(wallCheckPoint.position, wallCheckSize);
}
}
If there are other details you want to know, please let me know and i will edit this post with those details. Any help is appreciated, thanks! :)