Search Unity

  1. We are migrating the Unity Forums to Unity Discussions. On July 12, the Unity Forums will become read-only.

    Please, do not make any changes to your username or email addresses at id.unity.com during this transition time.

    It's still possible to reply to existing private message conversations during the migration, but any new replies you post will be missing after the main migration is complete. We'll do our best to migrate these messages in a follow-up step.

    On July 15, Unity Discussions will become read-only until July 18, when the new design and the migrated forum contents will go live.


    Read our full announcement for more information and let us know if you have any questions.

Question Properly detecting ceiling/colliders above player?

Discussion in 'Scripting' started by ResonantWilterUni, Feb 14, 2024.

  1. ResonantWilterUni

    ResonantWilterUni

    Joined:
    Jul 20, 2023
    Posts:
    55
    In games like Call of Duty when you climb into any kind of tight space like a vent in the ceiling, the process and animation seems so flawless and the player never clips into the ceiling or gets stuck.

    I have been trying to add ceiling detection like that when I try to crawl into one of those same tight spaces where my player must be crouched in order to enter it. I have it working for the most part, but there are some times where it does not work even though it should.

    What I do is I have a Raycast at the center of my player body that casts forward to handle climbing, and once that Raycast no longer detects a collider, then my player begins the climbing Lerp with a coroutine. At the exact same time 1 frame before the Lerp and once the Raycast is not hitting a collider, the SphereCast determines whether or not there is a ceiling above the player and then uses that information to either Lerp standing up (which means there is no ceiling), or Lerp and crouch simultaneously into the vent. If the vent is too small to crawl into, then the Lerp will never begin at all and I fall to the ground like normal, but in my case my player still tries to crawl into these.

    For example if my Character Controller has a default standing height of 2f and the height between the bottom of the vent and top of the vent (ceiling) is 1.998f, my player should automatically crouch prior to entering it, but instead, my player tries to enter with default height which results in my player clipping into the vent and getting stuck.

    I have tried BoxCast, OverlapSphere and OverlapBox and they were even worse. I debugged every single step and also used gizmos to visualise every single thing that I did and I still can't get 100% accuracy.
     
  2. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,654
    Have you tried putting triggers covering tbe ceiling areas? Inside the trigger = in a cieling space, and set your movement state accordingly. Then have rules about the height of your crawl spaces, where there can and can't be obstructions, etc., so that you can set up your animations and transitions to suit.

    Games like Call of Duty account for the stuff you're dealing with at design time as well as in code. Crawl spaces will fit certain criteria and be built to a spec, so that the code doesn't have to detect everything dynamically.

    Full dynamic detection is certainly possible, but super tricky to polish for arbitrary cases.
     
    Ryiah likes this.
  3. ResonantWilterUni

    ResonantWilterUni

    Joined:
    Jul 20, 2023
    Posts:
    55
    I thought about using triggers for a bit but would that be a bit tricky/time consuming because if there is a scene with many similar objects, would I have to manually add colliders with triggers around each of these objects? Currently just while I have been testing my ceilings, I have around 30 different ceiling type objects that I test
     
  4. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,654
    I wouldn't put triggers on every object, I'd put them over each crawl area. It's likely easier, and it's definitely fewer objects. (More objects = more work for the CPU.)
     
  5. ResonantWilterUni

    ResonantWilterUni

    Joined:
    Jul 20, 2023
    Posts:
    55
    Thanks for the information I'll give that a go
     
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,761
    I'd be more concerned with why a fundamental thing such as a simple SphereCast is not detecting a collider that is there i.e. a ceiling that doesn't move. Of course I'm assuming there's not some bug in your script such as not casting from the correct location etc.

    When I see the word "frame" or "lerp" in a physics-based thread, I tend to think about the many times I've seen the Transform being used as pose authority when it's actually the Rigidbody that has this correct information and the Transform (when using interpolation) is moving from the previous position to the current position.

    Unless the Rigidbody has significantly moved however, this discrepancy is often overlooked but there are times when things are moving fast, or repositioned or where the query has to be pretty accurate where it shows up.

    Also, in 3D physics, I don't believe those casts detect things they are already inside so that's another thing to watch out for.

    I only mention this because there are a few things to watch out for here.
     
    mopthrow and angrypenguin like this.
  7. ResonantWilterUni

    ResonantWilterUni

    Joined:
    Jul 20, 2023
    Posts:
    55
    Thanks for the reply. I've messed around a lot with the SphereCast origin position and currently I use:

    Code (CSharp):
    1. float downOffset = 0.5f; // lower the SphereCast
    2. Vector3 startPos = transform.position + transform.forward * 0.8f - Vector3.down * downOffset; // position the origin both forward + down
    3.  
    4. bool SphereCastUpwards = Physics.SphereCast(startPosition, 0.6f, Vector3.up, out sphereHit, 1.5f); // slightly increased radius of player
    5.  
    6. if (SphereCastUpwards)
    7. {
    8.     // Crawl into hole
    9. }
    Maybe the problem is because I'm not specifically checking if a collider was hit using something like
    sphereHit.collider != null
    , etc. Will test that now.

    upload_2024-2-14_22-9-0.png

    The SphereCast will only start casting once that magenta Raycast is no longer hitting the bottom grey rectangle/green square.

    My actual mechanic to crawl into this hole does have a lot of other code in it so I'm not sure if what I provided is useful in any way but I will continue to test with triggers and checking for specific hits.
     
  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,761
    Note that the Rigidbody is always at Rigidbody.position not Transform.position if you're moving and using interpolation.

    You don't need to check that, if it returns false then there are no results.

    No idea what the colliders are you're trying to detect here but as it says in the docs, "Notes: SphereCast will not detect colliders for which the sphere overlaps the collider." so you must be careful here.
     
  9. ResonantWilterUni

    ResonantWilterUni

    Joined:
    Jul 20, 2023
    Posts:
    55
    Oh my bad, I am only using the in-built CharacterController component and have no Rigidbody attached to my player (or colliders). This might be really bad but I couldn't find any other info online so I did it myself, when I use Vector3.Lerp I actually have an invisible GameObject as a child of my Player object and I position it slightly above and infront of my player, roughly where the top drawn red Sphere in the photo is. Then to Lerp, I just take its position right as the magenta Raycast stops hitting a collider and I use that position as my target position.

    And yeah, I don't mind that the origin of the SphereCast overlaps the floor (the green portion of the cube) as it still casts upwards and hits the ceiling which is good.
     
  10. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,761
    Sorry, that's my fault for not seeing that you mentioned that! :)