- Home /
Can someone help me implement crouch (2d)
I am trying to implement a crouch function without using a pre-made character controller, but it just won't work. For some reason I have to press ctrl multiple times for my character to either stand up or crouch, and I don't get why. I tried searching but it seams not many people program this way. Here's my code: using System.Collections; using System.Collections.Generic; using UnityEngine;
public class move : MonoBehaviour {
Rigidbody2D rb2d;
SpriteRenderer spriterender;
BoxCollider2D bcol;
bool crouch = false;
[SerializeField]
private LayerMask platformLayerMask;
// Start is called before the first frame update
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
spriterender = GetComponent<SpriteRenderer>();
bcol = GetComponent<BoxCollider2D>();
}
// Update is called once per frame
void FixedUpdate()
{
if (crouch == true)
{
bcol.enabled = false;
}
else if (crouch == false) { bcol.enabled = true; }
if (Input.GetKey("d") || Input.GetKey("right"))
{
rb2d.velocity = new Vector2(4, rb2d.velocity.y);
spriterender.flipX = false;
}
////////
else if (Input.GetKey("a") || Input.GetKey("left"))
{
rb2d.velocity = new Vector2(-4, rb2d.velocity.y);
spriterender.flipX = true;
}
////////
else
{
rb2d.velocity = new Vector2(0, rb2d.velocity.y);
}
////////
if (IsGrounded() && Input.GetKey("space") || Input.GetKey("up") && IsGrounded())
{
rb2d.velocity = new Vector2(rb2d.velocity.x, 17);
}
if (Input.GetKeyDown(KeyCode.LeftControl))
{
crouch = true;
rb2d.velocity = new Vector2((rb2d.velocity.x) / 2, (rb2d.velocity.y) - 5);
Debug.Log("crouching");
}
if (Input.GetKeyUp(KeyCode.LeftControl))
{
crouch = false;
rb2d.velocity = new Vector2(rb2d.velocity.x, rb2d.velocity.y);
Debug.Log("standing");
}
}
////////////////
private bool IsGrounded()
{
RaycastHit2D raycastHit = Physics2D.BoxCast(bcol.bounds.center, bcol.bounds.size, 0f, Vector2.down, 1f, platformLayerMask);
Color rayColor;
if (raycastHit.collider != null)
{
rayColor = Color.green;
}
else
{
rayColor = Color.red;
}
Debug.DrawRay(bcol.bounds.center + new Vector3(bcol.bounds.extents.x, 0), Vector2.down * (bcol.bounds.extents.y + 1f), rayColor);
Debug.DrawRay(bcol.bounds.center - new Vector3(bcol.bounds.extents.x, 0), Vector2.down * (bcol.bounds.extents.y + 1f), rayColor);
Debug.DrawRay(bcol.bounds.center - new Vector3(bcol.bounds.extents.x, bcol.bounds.extents.y, 1f), Vector2.right * (bcol.bounds.extents.y), rayColor);
return raycastHit.collider != null;
}
}
Small update: Today I tried the same code, and the first time it worked, but then it stopped working for some reason
Answer by MADiFold · Aug 11, 2021 at 10:58 AM
please please please put your actions, state checks and drawing of debugs in different functions. In the code provided it is cumbersome to find anything. It will help you debug it yourself too.
Using Raycasts is a fickle thing to decide whether the character is colliding (constantly), you could try with a onCollisionStay for grounding, but still that would also work on stuff in other normalized directions. What I mean is that the RayCast (if set too short, like only 1 or 2 pixels outside the bounds) might miss and hit in several frames. This is why I would put these items in separate functions AND do detection in Update rather than FixedUpdate. (StackOverflow: Update runs once per frame. FixedUpdate can run once, zero, or several times per frame, depending on how many physics frames per second are set in the time settings, and how fast/slow the framerate is.). If you put the isGrounded public in inspector, you will see that the state is constantly changing even when the sprite is 'steady'. Put a delay on the detection to make sure you are 'grounded' for several frames. This will help, but first break up your code to represent well formatted.
I will be honest with you. I am still really new to this stuff and didn't understand everything you said, but I did understand a few things and appreciate the criticism. Thanks for the help, I will follow your advise
Just to let you know, I dicided not to put your corrections yet because I would have to rewrite everything, sorry, please don't get mad
Answer by Kaizara · Aug 11, 2021 at 12:19 PM
Fixed! Corrected code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class move : MonoBehaviour
{
Rigidbody2D rb2d;
SpriteRenderer spriterender;
BoxCollider2D bcol;
bool crouch = false;
[SerializeField]
private LayerMask platformLayerMask;
// Start is called before the first frame update
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
spriterender = GetComponent<SpriteRenderer>();
bcol = GetComponent<BoxCollider2D>();
}
// Update is called once per frame
void FixedUpdate()
{
if (crouch == true)
{
bcol.enabled = false;
}
else if (crouch == false) { bcol.enabled = true; }
if (Input.GetKey("d") || Input.GetKey("right"))
{
rb2d.velocity = new Vector2(4, rb2d.velocity.y);
spriterender.flipX = false;
}
////////
else if (Input.GetKey("a") || Input.GetKey("left"))
{
rb2d.velocity = new Vector2(-4, rb2d.velocity.y);
spriterender.flipX = true;
}
////////
else
{
rb2d.velocity = new Vector2(0, rb2d.velocity.y);
}
////////
if (IsGrounded() && Input.GetKey("space") || Input.GetKey("up") && IsGrounded())
{
rb2d.velocity = new Vector2(rb2d.velocity.x, 17);
}
if (Input.GetKey(KeyCode.LeftControl))
{
crouch = true;
rb2d.velocity = new Vector2((rb2d.velocity.x) / 2, (rb2d.velocity.y) - 5);
Debug.Log("crouching");
}else
{
crouch = false;
rb2d.velocity = new Vector2(rb2d.velocity.x, rb2d.velocity.y);
Debug.Log("standing");
}
}
////////////////
private bool IsGrounded()
{
RaycastHit2D raycastHit = Physics2D.BoxCast(bcol.bounds.center, bcol.bounds.size, 0f, Vector2.down, 1f, platformLayerMask);
Color rayColor;
if (raycastHit.collider != null)
{
rayColor = Color.green;
}
else
{
rayColor = Color.red;
}
Debug.DrawRay(bcol.bounds.center + new Vector3(bcol.bounds.extents.x, 0), Vector2.down * (bcol.bounds.extents.y + 1f), rayColor);
Debug.DrawRay(bcol.bounds.center - new Vector3(bcol.bounds.extents.x, 0), Vector2.down * (bcol.bounds.extents.y + 1f), rayColor);
Debug.DrawRay(bcol.bounds.center - new Vector3(bcol.bounds.extents.x, bcol.bounds.extents.y, 1f), Vector2.right * (bcol.bounds.extents.y), rayColor);
return raycastHit.collider != null;
}
}
Cool, glad you figured it out yourself (because that's the best feeling no doubt)....also I'd recommend converting your comment to an answer and accepting it to facilitate answer for future visitors....and all the best with the game you're making
Your answer

Follow this Question
Related Questions
Collision Problem with AVATAR 0 Answers
Stealth tutorial sneak bool? 0 Answers
Modifying crouch script using Slerp 0 Answers
Detect collision when changing character controller height 2 Answers
Crouching Script 1 Answer