Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question How To Stop Uncrouching Under Object

Discussion in 'Scripting' started by brygonnn, Aug 4, 2023.

  1. brygonnn

    brygonnn

    Joined:
    Jun 22, 2023
    Posts:
    10
    Every time that I crouch and stand up under an object I phase through it, does anyone have a solution? I have posted about this and haven't been able to find a solution yet.
    I don’t use rigid body so here’s the code
    Code (CSharp):
    1. public class PlayerMotor : MonoBehaviour
    2. {
    3.  
    4.     private CharacterController controller;
    5.     private Vector3 playerVelocity;
    6.     public float speed = 2f;
    7.     private bool isGrounded;
    8.     public float gravity = -9.8f;
    9.     bool lerpCrouch = false;
    10.     bool crouching = false;
    11.     bool sprinting = false;
    12.     float crouchTimer;
    13.  
    14.     void Start()
    15.     {
    16.         controller = GetComponent<CharacterController>();
    17.     }
    18.  
    19.     void Update()
    20.     {
    21.         isGrounded = controller.isGrounded;
    22.         if (lerpCrouch)
    23.         {
    24.             crouchTimer += Time.deltaTime;
    25.             float p = crouchTimer / 1;
    26.             p *= p;
    27.             if (crouching)
    28.                 controller.height = Mathf.Lerp(controller.height, 1, p);
    29.             else
    30.                 controller.height = Mathf.Lerp(controller.height, 2, p);
    31.  
    32.             if (p > 1)
    33.             {
    34.                 lerpCrouch = false;
    35.                 crouchTimer = 0f;
    36.             }
    37.         }
    38.     }
    39.     public void Crouch()
    40.     {
    41.         crouching = !crouching;
    42.         crouchTimer = 0;
    43.         lerpCrouch = true;
    44.         if (crouching && sprinting)
    45.             speed = 1;
    46.         if (crouching)
    47.             speed = 1;
    48.         else
    49.             speed = 2;
    50.     }
    51.     public void Sprint()
    52.     {
    53.         sprinting = !sprinting;
    54.         if (sprinting)
    55.             speed = 4;
    56.         else
    57.             speed = 2;
    58.         if (crouching && sprinting)
    59.             speed = 1;
    60.     }
    61.     public void ProcessMove(Vector2 input)
    62.     {
    63.         Vector3 moveDirection = Vector3.zero;
    64.         moveDirection.x = input.x;
    65.         moveDirection.z = input.y;
    66.         controller.Move(transform.TransformDirection(moveDirection) * speed * Time.deltaTime);
    67.         playerVelocity.y += gravity * Time.deltaTime;
    68.         if (isGrounded && playerVelocity.y < 0)
    69.             playerVelocity.y = -2f;
    70.         controller.Move(playerVelocity * Time.deltaTime);
    71.         Debug.Log(playerVelocity.y);
    72.     }
    73. }
    There is no standing option, only a camera position as well as a crouching action. As a previous user mentioned, using ray cast should have done the trick but it didn’t work. This has halted my progress for months and hope someone knows how to help. Thank you.
    (I want to point out that I'm new to coding and suck at it, so I used a tutorial)
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,561
    Time to start debugging! If you can't tell, nobody here can either.

    If you don't want to fix your code, grab the controller at the bottom of this message. I just verified it crouches AND does not allow full standing if you're under a ledge and crouching.

    Here is how you can begin your exciting new debugging adventures:

    You must find a way to get the information you need in order to reason about what the problem is.

    Once you understand what the problem is, you may begin to reason about a solution to the problem.

    What is often happening in these cases is one of the following:

    - the code you think is executing is not actually executing at all
    - the code is executing far EARLIER or LATER than you think
    - the code is executing far LESS OFTEN than you think
    - the code is executing far MORE OFTEN than you think
    - the code is executing on another GameObject than you think it is
    - you're getting an error or warning and you haven't noticed it in the console window

    To help gain more insight into your problem, I recommend liberally sprinkling
    Debug.Log()
    statements through your code to display information in realtime.

    Doing this should help you answer these types of questions:

    - is this code even running? which parts are running? how often does it run? what order does it run in?
    - what are the names of the GameObjects or Components involved?
    - what are the values of the variables involved? Are they initialized? Are the values reasonable?
    - are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

    Knowing this information will help you reason about the behavior you are seeing.

    You can also supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as
    Debug.Log("Problem!",this);


    If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

    You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

    You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

    You could also just display various important quantities in UI Text elements to watch them change as you play the game.

    Visit Google for how to see console output from builds. If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer for iOS: https://forum.unity.com/threads/how-to-capturing-device-logs-on-ios.529920/ or this answer for Android: https://forum.unity.com/threads/how-to-capturing-device-logs-on-android.528680/

    If you are working in VR, it might be useful to make your on onscreen log output, or integrate one from the asset store, so you can see what is happening as you operate your software.

    Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

    If your problem is with OnCollision-type functions, print the name of what is passed in!

    Here's an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

    https://forum.unity.com/threads/coroutine-missing-hint-and-error.1103197/#post-7100494

    "When in doubt, print it out!(tm)" - Kurt Dekker (and many others)

    Note: the
    print()
    function is an alias for Debug.Log() provided by the MonoBehaviour class.

    Otherwise, if you just want a basic FPS controller that has a crouch and the crouch won't stand up when there's something overhead, here's one:

    https://forum.unity.com/threads/a-basic-first-person-character-controller-for-prototyping.1169491/

    That one has run, walk, jump, slide, crouch... it's crazy-nutty!!

    For future reference...

    How to report your problem productively in the Unity3D forums:

    http://plbm.com/?p=220

    This is the bare minimum of information to report:

    - what you want
    - what you tried
    - what you expected to happen
    - what actually happened, log output, variable values, and especially any errors you see
    - links to documentation you used to cross-check your work (CRITICAL!!!)

    The purpose of YOU providing links is to make our job easier, while simultaneously showing us that you actually put effort into the process. If you haven't put effort into finding the documentation, why should we bother putting effort into replying?
     
  3. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    I assume someone mentioned if you raycast from root position(ground/center of player) up, when "trying" to stand back up, the raycast should see the static layer of map, and determine that the height is not high enough to stand, therefor cancelling the stand up action. Which is one way of doing it, yes.

    Another way would be have your character collider shrink in height(same as player crouching height), and when trying to "stand up" the collision would check if it hits the static layer of the play map and cancel said "standing up" and continue crouched.

    But yeah, if you force a collider into another one, it will clip, and either get stuck, or fall through the map.
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,561
    Whoops, just looked at your code. Unfortunately it calls .Move() twice per frame. That will cause all manner of issues.

    bad.png

    This must be taken from that annoyingly defective tutorial that comes up so much. I wish I could find that and have it taken down. Here's why:

    CharacterController CharMover broken:

    I wrote about this before: the Unity example code in the API no longer jumps reliably.

    If you call .Move() twice in one single frame, the grounded check may fail.

    I reported it to Unity via their docs feedback in October 2020. Apparently it is still broken:

    https://docs.unity3d.com/ScriptReference/CharacterController.Move.html

    Here is a work-around:

    https://forum.unity.com/threads/how...racter-movement-in-unity.981939/#post-6379746

    I recommend you also go to that same documentation page and ALSO report that the code is broken.

    When you report it, you are welcome to link the above workaround. One day the docs might get fixed.

    If you would prefer something more full-featured here is a super-basic starter prototype FPS based on Character Controller (BasicFPCC):

    https://forum.unity.com/threads/a-basic-first-person-character-controller-for-prototyping.1169491/

    That one has run, walk, jump, slide, crouch... it's crazy-nutty!!
     
  5. brygonnn

    brygonnn

    Joined:
    Jun 22, 2023
    Posts:
    10
    So I understand what you mean here, but since I really don't understand unity 100%, how do you think I should redo this part to make sure that I don't call .Move() twice without breaking my code?
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,561
    So you didn't look at the link where I showed you EXACTLY how to redo the script???

    I'll wait.

    Or you're welcome to just use the other script.

    I am just not going to keep re-solving the same problem I've already solved twice in my post above.
     
  7. brygonnn

    brygonnn

    Joined:
    Jun 22, 2023
    Posts:
    10
    I have tried as someone has tried telling me the same thing but it didn't work, here's what they gave me, and I did try to modify both codes given to me to no success.
    https://discussions.unity.com/t/standing-up-while-crouching/270324/2
     
  8. brygonnn

    brygonnn

    Joined:
    Jun 22, 2023
    Posts:
    10
    Maybe I clicked on a link twice, my apologies, I'll check right now
     
  9. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    Well to be fair, that raycast doesn't have any checks for layers, so it would probably hit the player collider and immediately be false. But you want it to look for whatever layer you have the playMap, or other objects set to for collisions so player doesn't stand through them.

    Raycasts are fun, a little performance heavy(in my opinion), but they do work great. The only thing is you gotta keep playing with them. Always set your "start" and "direction" variables, so you can also use Debug.DrawLine(). So you can physically see them(with gizmos on(Scene View)) and correctly set directions or length of the ray.

    But as DrawLine says, Debug! Keep messing with values, and print out collision hits, so you know exactly what it's doing and why.

    For sure you want some kind of check in place, if character crouched, crawling through a crawl space, you don't want him standing. But just keep at it, the more you learn raycasts the more ideas of crazy things you can do with them! :)
     
  10. brygonnn

    brygonnn

    Joined:
    Jun 22, 2023
    Posts:
    10
    I get what you're saying, I'll let you know what I come up with, but before I start, how can I make a debug check for layers? Thanks.
     
  11. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    I don't know why this snippet is in my old notes, lol, the use functions are more caveman than I!
    Code (CSharp):
    1. public class RaycastTest : MonoBehaviour {
    2. float lenthRay = 10.0f;
    3. Vector3 originePos;
    4. Vector3 dir;
    5. RaycastHit hitinfo;
    6. GameObject hitten;
    7. bool isHitting;
    8. Color beforC;
    9. int selectionLayer = 9;
    10.  
    11. void Update () {
    12.     originePos = Camera.main.transform.position;
    13.     dir = Camera.main.transform.forward * lenthRay;
    14.     Debug.DrawRay(originePos, dir, Color.blue);
    15.  
    16.     if (Physics.Raycast(originePos, dir, out hitinfo, lenthRay , selectionLayer)) {
    17.         hitten = hitinfo.transform.gameObject;
    18.         MeshRenderer tmp = hitten.transform.GetComponent<MeshRenderer>();
    19.         beforC = tmp.material.color;
    20.         tmp.material.color = Color.black;
    21.     }
    22. }
    But in all fairness, it should give you some pointers on what I meant in my previous post.
     
  12. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    Sorry! totally missed that part.

    This post should help, as I see some good pointers in it:
    https://forum.unity.com/threads/defining-layers-in-raycast.36349/

    But mostly I meant, by debug, is
    print($"ray hit {collider.name}");
    and then play around with the layers so that it ignores the player, as you only want it to hit wall/ceiling/object/etc...