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

Make character follow along walls & ceiling?

Discussion in 'Physics' started by SgtSargeMcFly, Jan 6, 2022.

  1. SgtSargeMcFly

    SgtSargeMcFly

    Joined:
    May 4, 2020
    Posts:
    20
    I'm trying to make a sidescroller game where the character can stick to the walls and ceiling and move along them like a buzzsaw cutting into the floor.
    upload_2022-1-6_0-41-11.png

    So basically, motions like this should be possible.

    I'm having an extremely tough time figuring out how to do this. I'm able to at least get the player to adhere to slopes on the floor, I have a downward SphereCast that gets the normal and adjusts the player's velocity according to it. However, it gets problematic when you have to SphereCast in different directions to detect walls and the ceiling, not to mention the slopes on both of those things. I'm struggling to find a way to decide which direction to spherecast in and when, because my current approach where I spherecast in all four cardinal directions isn't working so far, though there are things I haven't tried yet like getting all collision points from the four casts and comparing them to somehow decide which is the "right" one.

    -I'm using a CharacterController. My script calculates what direction the player is supposed to move in, and at the very end of the script CharacterController.Move is called.

    -OnControllerColliderHit seemed really promising, but when I added a bit to my script to draw a line from the player's position to the hit point, it started returning really weird values nowhere close to where the character was standing.

    -Physics.OverlapSphere doesn't seem to work in this case as it doesn't return the normal or a point I can raycast to to get the normal.

    So far I've also only been working at trying to make a script that lets the player scale inner perimeters, for outer perimeters (like the floating platform in the screenshot) I have no earthly idea how I'll approach it, so no trouble if you can't explain that part.

    If anyone can point me in the right direction I'd be really thankful!
     
    Last edited: Jan 6, 2022
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,762
    I remember you posted about this before and we chatted... I messed around with it and came up with a simple proof of concept for a character moving along the 2D ground, sticking to it always.

    This demo also includes leaping "up" to another platform.

    Full project enclosed.



    platform_chaser_2d.png
     

    Attached Files:

    Last edited: Jan 7, 2022
    SgtSargeMcFly likes this.
  3. SgtSargeMcFly

    SgtSargeMcFly

    Joined:
    May 4, 2020
    Posts:
    20
    This is incredibly nice of you to write all this code for me, thank you so much, I could never ask anyone to put together this much for me! I'm exhausted today so I'm gonna wait till tomorrow to digest all this, but one thing I wanted to ask just from glancing at it:

    You increased the raycast origin by the SensingCastLift to "avoid entering slopes," can you clarify what you mean by this? I understand that raycasting from the bottom of the character to the ground might be janky considering how close they are, but aren't you raycasting from the center of your character (transform.position)? Doesn't that leave a good deal of distance between the raycast origin and the ground? Why is the SensingCastLift necessary? (Unless you have the character's center set to the bottom)
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,762
    It's exactly that. The player's position is bottom center. If we cast from there, then the instant we went right and encountered rising ground, we would be casting from within the ground and wouldn't sense it.

    I updated the graphic within the project. Look at the stuff in the lower right corner detailing this.
     
  5. SgtSargeMcFly

    SgtSargeMcFly

    Joined:
    May 4, 2020
    Posts:
    20
    Hope no one minds if I bump, since Kurt-Dekker's code only covered inward rotations I'm trying to tackle the outward ones myself after seeing how he approached it. I have some code that's worked pretty well but I'm getting the weirdest glitch and I have no earthly idea what could be causing it.

    upload_2022-1-12_20-14-46.png

    Here, the star is climbing along the ceiling. The red line is its forward vector, and the blue line is its down vector. The problem starts when we get onto that slope.

    upload_2022-1-12_20-15-55.png

    For the first frame of movement, the vectors align themselves to the surface just as I want them to. If I stay in place like this, they'll remain consistent, but the very next frame I try to move....

    upload_2022-1-12_20-17-10.png

    The star randomly jumps up a little, enough for it to stop detecting that there's ground below it. If I have gravity turned on this makes the star abruptly detach from the wall. However, even with gravity turned off, this still happens. The effect becomes even more exaggerated if my movement speed is higher.

    I'm completely stumped because I don't even have much code to examine for things that could be causing this. This is all that the script is running:

    Code (CSharp):
    1. //---------GATHER DIRECTION INTENTS-------------
    2.         float inputDirV = Input.GetAxisRaw("Vertical");
    3.         float inputDirH = Input.GetAxisRaw("Horizontal");
    4.         bool jumpKey = Input.GetButtonDown("Jump");
    5.  
    6.         if (inputDirV != 0)
    7.             lastKnownMove = inputDirV;
    8.  
    9.  
    10.         //---------FIND CURRENT GROUND------------------
    11.         Vector3 bottomCenter = transform.position + (downVector * cc.bounds.extents.y);
    12.         Physics.SphereCast(transform.position, cc.bounds.extents.x, downVector, out RaycastHit groundInfo, 1.0f, LayerMask.GetMask("ground"));
    13.         Physics.SphereCast(transform.position, cc.bounds.extents.x, forwardVector * lastKnownMove, out RaycastHit forwardInfo, 0.5f, LayerMask.GetMask("ground"));
    14.  
    15.  
    16.         if (forwardInfo.collider)
    17.         {
    18.             forwardVector = Quaternion.FromToRotation(-downVector, forwardInfo.normal) * forwardVector;
    19.             downVector = -forwardInfo.normal;
    20.         }
    21.  
    22.         Vector3 moveDir = forwardVector * inputDirV * walkSpeed;
    23.  
    24.  
    25.         //-------------JUMPING & GRAVITY-------------------
    26.         bool isGrounded = (groundInfo.collider || forwardInfo.collider);
    27.  
    28.         if (!isGrounded)
    29.             moveDir.y += gravity;
    30.  
    31.         cc.Move(moveDir);
    I should note that it's using a Character Controller (cc) but toying around with skin width, step offsets, etc haven't seemed to change much. The only fix has been to greatly increase the ground raycast length, which only creates new jank elsewhere. If anyone has any idea what might be going on please let me know!
     
  6. SgtSargeMcFly

    SgtSargeMcFly

    Joined:
    May 4, 2020
    Posts:
    20
    Bumping this hoping I may get some insight, the problem in the post above brought a screeching halt to all my progress and I gave up for a few months. But even with a fresh pair of eyes I can't figure this out. Could FromToRotation be returning something faulty?
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,762
    I'm not sure you can spin the CharacterController around to walk on the ceiling like that. I've seen folks having issues just getting the CharacterController to "wall walk," let alone walk on the ceiling. Is that the problem?

    First check the above, but as far as identifying if a rotation is correct, one way is to feed the rotation to another little 3D object with X,Y,Z arrows / spikes, and see if it is reasonable in realtime. You can make a little object ouf of cube and / or sphere primitives, color the spikes red/green/blu and you have a handy tool that took like 60 seconds to make.
     
  8. SgtSargeMcFly

    SgtSargeMcFly

    Joined:
    May 4, 2020
    Posts:
    20
    Thanks for coming back to this thread so much later. Since I can't figure anything else out I might as well try getting rid of the CharacterController and just moving using Translate. I'll try the arrow thing too!
     
  9. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,529
    I'd like to suggest you use the Physics forum and not the 2D forum if you're discussing 3D physics.

    I can, of course, move this thread there if you wish.

    Thanks.
     
  10. SgtSargeMcFly

    SgtSargeMcFly

    Joined:
    May 4, 2020
    Posts:
    20
    I'd be fine with that, even though it's taking place in a 3D space it is still a 2D perspective so I figured it might fit here.

    @Kurt-Dekker yeah, I'm having much better luck just using a SphereCollider and Rigidbody, I have NO idea why I put off trying that for so long or why I was so attached to using the charactercontroller. Thanks for all your help!
     
  11. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,529
    So yes, the 2D forum is not for any problem whilst using Orthographic perspective on the camera. 2D is a set of 2D features put out by the 2D team.

    A 3D physics question should not be posted on the 2D forum. I'll move your post to the dedicated and correct forum.
     
  12. tjmaul

    tjmaul

    Joined:
    Aug 29, 2018
    Posts:
    464
    Might this help?
    https://m.youtube.com/watch?v=AhywDyu0EGw
    I watched that some time ago and although the procedural animation is probably not interesting for you, you might be able to take something out of the general system