Help With Crouching Colliders

I am trying to add a crouching script to my game which allows me to crouch when I press “c.” That is working properly, along with the sprinting in the script, but when I am under something and uncrouch, I clip through the object and can walk around normally. Can someone help me to fix this problem? If possible, to make it slightly easier, could the fixed script be posted? Thank you.

Script:

using UnityEngine;
using System.Collections;

public class RunAndCrouch : MonoBehaviour
{
    public float walkSpeed = 7; // regular speed
    public float crchSpeed = 3; // crouching speed
    public float runSpeed = 20; // run speed
 
    private CharacterMotor chMotor;
    private Transform tr;
    private float dist; // distance to ground
 
    // Use this for initialization
    void Start ()
    {
        chMotor =  GetComponent<CharacterMotor>();
        tr = transform;
        CharacterController ch = GetComponent<CharacterController>();
        dist = ch.height/2; // calculate distance to ground
    }
 
    // Update is called once per frame
    void FixedUpdate ()
    {
        float vScale = 1.0f;
        float speed = walkSpeed;
     
        if ((Input.GetKey("left shift") || Input.GetKey("right shift")) && chMotor.grounded)
        {
            speed = runSpeed;          
        }
     
        if (Input.GetKey("c"))
        { // press C to crouch
            vScale = 0.5f;
            speed = crchSpeed; // slow down when crouching
        }
     
        chMotor.movement.maxForwardSpeed = speed; // set max speed
        float ultScale = tr.localScale.y; // crouch/stand up smoothly
     
        Vector3 tmpScale = tr.localScale;
        Vector3 tmpPosition = tr.position;
     
        tmpScale.y = Mathf.Lerp(tr.localScale.y, vScale, 5 * Time.deltaTime);
        tr.localScale = tmpScale;
     
        tmpPosition.y += dist * (tr.localScale.y - ultScale); // fix vertical position      
        tr.position = tmpPosition;
    }
}

Please use coding tags.

Have you tried adding some kind method to check if the character can stand?
“ValidateStand()”, perhaps. If it cant stand, it’ll stay crouched.

I find it can help to have a standing check similar to how you make a ground check for jumping, just raycast upwards to the distance of the player when standing and not let the player leave the crouching state if there is a collision on that ray.

Other option is instead of resizing the players collider just use 2. When standing disable the crouch collider when crouching enable the crouching collider and change the standing one to a trigger, and only let the player switch to the standing state if there is nothing in the trigger.

Could you please explain how I would go about adding a raycast to check for a collider to prevent the character from standing back up?

I would use the CapsuleCast to check for collider above the player, and use this to set a bool, than only let the player stand if crouch is not held down and if that bool you set is false.

You can use the layer mask arugmeant to decide what objects count as a collision.

I have researched many ways to try and implement this into the script, but I can’t figure out how to correctly implement it. Are you able to explain where and how I would add it, and possibly why so I can learn?

I can make a exemple up tomorrow, cant right now since I’m not at my proper computer

Okay, thank you.

Is anyone else able to help or show me an example?

oh sorry for not getting back to you.
you could make a method like this one

using UnityEngine;
using System.Collections;

public class PlayerPawn : MonoBehaviour
{
    [SerializeField] private float _standHeight = 0.5f;
    [SerializeField] private float _radius = 0.5f;
    [SerializeField] private LayerMask _terrianLayers;

    private bool CanStand()
    {
        return Physics.CheckCapsule(transform.position, transform.position + new Vector3(0f, _standHeight, 0f), _radius,
            _terrianLayers);
    }
}

to check to see if there are colliders above the player while he is crouched.
just toss it into a if statemeant, and if it returns true, dont let the charcter stand, if it is false let the charcter stand.

Also in the _terrianLayers property make sure the player isnt on any of those layers, or lese the Capsule cast will hit the player and always return true.

1 Like

While trying to figure out how to use raycasts at school, I did manage to find a way to make one and have it output a message in the console saying “Hit.”

#pragma strict

function Update () {
   var up = transform.TransformDirection(Vector3.up);
   var hit : RaycastHit;   
   Debug.DrawRay(transform.position, up * 1.1, Color.green);
   if(Physics.Raycast(transform.position, up, hit, 1.1)){
      Debug.Log("Hit"); 
   
   }
}

I tried using a website to convert it to C#, www.m2h.nl/files/js_to_c.php, and it gave me this:

   FIXME_VAR_TYPE up= transform.TransformDirection(Vector3.up);
   RaycastHit hit;   
   Debug.DrawRay(transform.position, up * 1.1f, Color.green);
   if(Physics.Raycast(transform.position, up, hit, 1.1f)){
      Debug.Log("Hit"); 
   
   }
}

From here, I tried inserting it into my original script under when I press “C” and I changed “FIXME_VAR_TYPE” to “var”, which be the cause of my current error, but I am not quite sure. I also inserted the Serial Fields into the script to try and make the process a bit simpler later on. Under my crouching I have this:

if (Input.GetKey("c"))
        { // press C to crouch
            vScale = _standHeight;
            speed = crchSpeed; // slow down when crouching
            var up= transform.TransformDirection(Vector3.up);
            RaycastHit hit;   
            Debug.DrawRay(transform.position, up * 1.1f, Color.green);
           
            if(Physics.Raycast(transform.position, up, hit, 1.1f)){
                Debug.Log("Hit"); 
                }
        }

And I am getting three errors:

  1. Assets/Scripts/Crouching/RunAndCrouch.cs(50,68): error CS0165: Use of unassigned local variable `hit’
    , my prio

  2. Assets/Scripts/Crouching/RunAndCrouch.cs(50,36): error CS1502: The best overloaded method match for `UnityEngine.Physics.Raycast(UnityEngine.Vector3, UnityEngine.Vector3, out UnityEngine.RaycastHit, float)’ has some invalid arguments

  3. Assets/Scripts/Crouching/RunAndCrouch.cs(50,36): error CS1620: Argument #3' is missing out’ modifier

I know that once I can resolve these errors, I should be able to make it to where I remain crouched if there is something above me, as detected by the raycast cast above the character when they crouch. I just need to figure out how to make it to when a ceiling is detected, how to make the character remain in the crouched position. But, my first priority is fixing the errors. Could you help me to figure out what I have done wrong?

Passerby?

I won’t have time to look at it for a few days since I’m busy with a big move at work. But at a glance at it you simply put “out” in front of hit, in your raycast command it will remove all 3 errors.

 if(Physics.Raycast(transform.position, up,  out hit, 1.1f)){
                Debug.Log("Hit");
}
1 Like

Oh, wow, one small mistake can cause so many issues. Thank you so much. Now the only thing left to do is figure out how to keep the character crouch while the raycast is being hit.

Oh wait a minute, I have gotten it to work! Thank you so much! I had a bit of trouble with it being under when I was holding down “C,” so I moved it below to test if it was being hit, and if it was, the vScale was forced to be the Standing Height variable.

if (Input.GetKey("c"))
        { // press C to crouch
            vScale = _standHeight;
            speed = crchSpeed; // slow down when crouching

        }

        var up= transform.TransformDirection(Vector3.up);
        RaycastHit hit;   
        Debug.DrawRay(transform.position, up * 1.1f, Color.green);
       
        if(Physics.Raycast(transform.position, up, out hit, 1.1f)){
            Debug.Log("Hit");
            vScale = _standHeight;
        }

But what if the the room is an inverted cube? Adding a raycast to it will make it detect the room even if the roof is way up above him

Sorry to necro but this was a sweet bit of code - once tweaked :stuck_out_tongue:

                var up = transform.TransformDirection(Vector3.up);
                RaycastHit hit;

                if (!Physics.Raycast(transform.position, up, out hit, 5))
                {
                    crouching = false;
                    thisCharController.height = standheight;
                }

This will now allow player to un-crouch if there is 5m of clearance above. You could tweak that down or up depending on your needs but it works for getting my character to crawl through air vents.