Collide And Slide - *Actually Decent* Character Collision From Scratch

Поделиться
HTML-код
  • Опубликовано: 24 ноя 2024

Комментарии • 339

  • @cauhxmilloy7670
    @cauhxmilloy7670 Год назад +207

    It is nice to see push back on the annoying trend of internet replies which promote not trying and just generally being dumb. Making things from scratch, or making your own version of something, is very powerful. It's really at the heart of engineering, understanding, and creative expression. Thank you very much for promoting people to not just accept the status quo. Reinventing wheels isn't bad when available wheels suck. Instant like and subscribe.

    • @poke_gamedev
      @poke_gamedev  Год назад +51

      Yep. So much wrong with many of the resources available to beginner game devs. I literally just responded to another comment saying "tHiS iS cOmMoN kNoWlEdGe" and that the video is pointless. So even this guy who DOES know the "right" way doesn't want it to be shared for some reason!!! So much dismissal and gatekeeping all around.

    • @Gabriel-no6wv
      @Gabriel-no6wv Год назад +2

      E.X.A.C.T.L.Y

    • @user-og6hl6lv7p
      @user-og6hl6lv7p 10 месяцев назад +2

      @@poke_gamedev Tbf, the reason so much misinfo is being spread is precisely due to the lack of gatekeeping. People who aren't passionate about solving problems enter the field and just copy-paste code and tell people to do the same. There's nothing wrong with letting people in who are interested, but those who do not fundamentally care should probably be pushed away.

    • @lanchanoinguyen2914
      @lanchanoinguyen2914 8 месяцев назад

      Yes but it's far from making game engine.

    • @kevinquintana3085
      @kevinquintana3085 7 месяцев назад

      ​@@user-og6hl6lv7pyup but we have then two problems here gatekeeping and copy-pasters, gatekeeping prevents knowledge to be shared and as an extra we need to deal with the flexing, copy-pasters spreads the black box way of thinking should I say ¿? Also the Swept AABB algorithm from gamedev page doesn't works

  • @shadowofcat
    @shadowofcat Год назад +31

    bro came out of literally nowhere and made one of the most helpful and high quality ive seen in a very long time

  • @Sophed
    @Sophed Год назад +157

    This is unreasonably underrated, incredibly high quality content. Keep it up man

    • @BleachWizz
      @BleachWizz Год назад +1

      the video literally starts with a tale i've been trough. I've been looking up to specifics on the collide and slide in video form for a while man...

    • @appleseedgames6934
      @appleseedgames6934 8 месяцев назад

      @@BleachWizz I don't understand why you didn't just use a rigidbody controller this whole time, literally the same but better. Seems there's 4.9k people who should've just used Google to learn what a rigidbody is lmao

    • @brollerchannel819
      @brollerchannel819 4 месяца назад

      @@appleseedgames6934 we are interested in how it all works. This is how we develop our logic, and we can do something based on this

  • @kasperfauerby7389
    @kasperfauerby7389 Год назад +73

    I'm happy to see you found my old paper useful! Not quite sure I follow the reasoning behind normalizing and re-adjusting the length of the projected vector in the sliding part, but this has been discussed in the comment section already ;) Great presentation and great video though!

    • @DrazkurHW
      @DrazkurHW Год назад

      ah I picked that up as well, glad I was not the only one

    • @enriquebp6070
      @enriquebp6070 Год назад

      Do you like Frank gambale?

    • @ghostbusterz
      @ghostbusterz Год назад +3

      Basically, when you project the velocity vector onto the vector (or plane) of the wall, it's length is only as long as the velocity vector *in the direction along the wall.* If he normalizes it, converting it to a unit vector (with length of 1), and then scales it by the length of the original velocity vector, he retains the full movement of the velocity vector but in a direction along the wall instead of into it.

    • @1234macro
      @1234macro 9 месяцев назад +3

      @@ghostbusterz It's more accurate to keep the rejection vector as-is. By normalizing and subsequently scaling, the object will always move at full speed when grinding against a wall because the surface normal will almost never be perfectly perpendicular to the object velocity.

    • @ghostbusterz
      @ghostbusterz 9 месяцев назад +3

      @@1234macro In video games we don't always want accuracy. It would be more physically accurate but that's not always what's most important for a given game's design.

  • @poke_gamedev
    @poke_gamedev  Год назад +154

    Update 2: Ok so Unity is currently imploding... I was working on refactoring and adding stair detection, but I might take a detour and learn Godot now lol
    As someone in the comments pointed out, maintaining full velocity on slopes is not very physically accurate, so I thought I should clarify that all the fancy scaling I'm doing is specifically meant for *character movement*, and should be ignored if using this code for a more general physics engine!
    Again, thanks for watching, and I hope you found this video helpful!

    • @uncleg1214
      @uncleg1214 Год назад

      And stairs?

    • @AgnisNeZvers
      @AgnisNeZvers Год назад +7

      It looks like that extra scaling with dot product ends up simulating the thing you already would get by projected slide. Although, it gives a control if you want to maintain full velocity.
      Also, In the place of a situation with a next wall, there is also an opposite problem - overshooting a corner.

    • @kenonerboy
      @kenonerboy Год назад +5

      That would convince me, if you didnt scale it again based on the angle between the wall and surface. You'd get that for free if you didnt scale the projected vector. Its also what happens irl minus the friction

    • @hi_its_jerry
      @hi_its_jerry Год назад +1

      im ready for waves of godot tutorials 🤤

    • @fernandes_L
      @fernandes_L Год назад +1

      I would like to see the next part with the stairs detection 😅

  • @albingrahn5576
    @albingrahn5576 Год назад +79

    good video! just wanted to point out that normalizing the vector at 4:00 only to multiply it by the dot product at 9:05 is unecessary since it reverses the normalization (it's like if you would multiply a number by 10 and then divide the result by 10, the second operation reverses the effects of the previous one). if you only want that "sliding along the wall" effect you can skip both steps to get the same result cheaper.

    • @rhedgeco
      @rhedgeco Год назад +23

      Was gonna come to say this ^
      I believe that's also part of the original paper. The slower sliding along the wall when more perpendicular appears naturally as a result of projecting the movement vector along the normal plane.

    • @TheChucknoxus
      @TheChucknoxus Год назад +4

      He makes a distinction between horizontal and vertical movement so no you do not get the same result

    • @kingbling7571
      @kingbling7571 Год назад

      U only move in horizontal tho

    • @official-obama
      @official-obama 6 месяцев назад

      @@TheChucknoxus but why not just not do the scaling at all?

  • @blinkachu5275
    @blinkachu5275 Год назад +11

    Thank you
    I have been on the receiving end of the dismissal quite often, when to me, yes, I could use the premade CharacterController or Rigidbody that does "everything for me" but like... I don't learn from that. All I learn is how to control that specific component, not how a Character Controller *actually* functions. Not how Collision *actually* functions.
    Most these people couldn't make a game without the use of these tools. Which is fine, the tools are there so it's fine to use them, but I am tired of the dismissal when someone is genuinely interested into just learning "what's under the hood"

    • @poke_gamedev
      @poke_gamedev  Год назад +5

      Yeah, not to mention that in Unity, the built-in character controller is just... not very good lol. It's honestly one of the main things Unreal and Godot have over Unity, and is definitely why the "uSe DyNaMiC rIgIdBoDy" suggestion pops up so often. People know it sucks but can't be bothered to actually find a better way.

    • @blinkachu5275
      @blinkachu5275 Год назад +2

      @@poke_gamedevyou're so right. Not being able to do anything on any other axis than the up axis in Unity with the CharacterController is so weird, you'd think they would've fixed it by now

  • @yuichikita6018
    @yuichikita6018 Год назад +113

    For Godot users: This is said in the documentation but, if you ever want to do this in Godot (with that I mean don't want to use the built in move_and_slide function), the engine provides the method move_and_collide() that does the collision casting + the movement, and the Vector2/3.slide() function to calculate the reaction movement.

    • @foxto100
      @foxto100 Год назад +15

      also, the move_and_slide, and move_and_collide both handle Collison overlapping so it will push out of a clipped surface.

    • @mohamedmoh5789
      @mohamedmoh5789 Год назад +2

      Wait , isn't the move_and_slide_on_slops function supposed to do this work for us ?

    • @yuichikita6018
      @yuichikita6018 Год назад +9

      ​@@mohamedmoh5789 I meant if you want to implement the movement yourself. Which is better if you want to have more control over the physics of the game.

    • @user-og6hl6lv7p
      @user-og6hl6lv7p 10 месяцев назад +1

      Doesn't work so good unfortunately. It sort of breaks and introduces horrid jitters if you introduce complex geometry.

    • @mikemhz
      @mikemhz 9 месяцев назад

      @@user-og6hl6lv7p What about when using the Jolt physics plugin?

  • @rhythmmmmm.
    @rhythmmmmm. Год назад +8

    This video probably would have helped me out tremendously a few years ago. I self taught myself Unity and refused to use anything anyone else made, so I spent probably a good year perfecting the movement in my own game, trying as hard as I could to figure out the stuff you're describing in this video. I eventually did it with a slightly different method, and I don't regret it because it ultimately taught me so much about the way things work, between time, frames, how acceleration, velocity, friction, etc work, but it's good that nobody else will have to go through the hell that I did.
    The issue you have described around the 10:30 mark ended up with my character getting their head stuck on any negative angle ramp collision, and at a certain point, actually ended up making them able to walk up the ceiling like a spider. I don't remember what I did to fix it, but I'll have to check out the paper on it.

  • @kruth6663
    @kruth6663 Год назад +4

    This is easily one of the best videos about movement and collision I've seen on youtube.

  • @yam-ingtonjr7606
    @yam-ingtonjr7606 Год назад +7

    such good visualization of vector math!

  • @lcppproductions7910
    @lcppproductions7910 4 месяца назад +2

    First of all, this video slaps, no question. I was struggling for some number of hours creating a controller for exploring a 2.5d top down map with potentially sloping terrain. I found solutions for moving on slopes, but there were always problems addressing steep slopes (among other things). This is the first video I've found that addresses those problems while still using a similar algorithm for moving up slopes.
    The one gripe I have is I don't like when people say something is the "right way" or "actually good" when it comes to programming, because there are multiple valid ways of doing things, and some people don't always have the time to implement everything from scratch. The Unity character controller addresses these problems and has parameters for slope limit, skin width, etc. It's a perfectly valid way of doing things. I just didnt want to use it in this instance because our game had potentially unique requirements, and I wanted to understand the math myself anyway.

  • @decofox6789
    @decofox6789 8 месяцев назад +5

    To anyone who's implemented this system:
    I am having an absolute hell of a time with glancing collisions. The first iteration consistently takes the player a little too far into the wall and results in the function getting stuck recursing, and for the life of me I cannot figure out why.
    I'm doing this in DOTS, so I don't have the luxury of a collider cast with a distance function. Instead I get a fraction. I suspect the problem is with how I'm performing the math for snapToSurface, which I've adapted to function with a fractional value like this:
    float3 snapToSurface= (vel * (hit.Fraction - (0.015f / (math.length(vel) + 0.015f))));
    The logic here is that math.length(vel)+0.015f is the expression that defines the original cast length, so I'm finding the equivalent of 0.015 in fraction-space, and subtracting it that way. That seems to work, but only at steep angles. Once the toward-the-collision component of velocity becomes low enough, I get stuck. I can only guess snapToSurface is ending up with too high of a value somehow, but I can't figure why.
    It also occured to me to calculate it this way:
    float hitDistance = (math.length(vel) + 0.015f) * hit.Fraction;
    float3 hitSurface = math.normalize(vel) * (hitDistance - 0.015f);
    but the results are the same.
    Anyone encounter a problem like that in their travels?

    • @decofox6789
      @decofox6789 8 месяцев назад +7

      Addendum - I've solved the problem. For others dealing with the same situation:
      This implementation seems to be missing a detail preventing infinitely recurring collisions on stationary colliders. This implementation deals with the problem by casting a skin width worth of extra distance ahead and then subtracting this value back out of the result, leaving the character controller against the wall plus the separation defined by skin width. The problem with this is it operates along the character's velocity vector, which, at very shallow angles, might have a component normal to the wall of nearly zero. Skin width will scale with that component, so if you have a glancing enough collision, the collider remains in touch with the wall and will collide infinitely. The effect of this is very obvious if you use a very large skin width and then run directly at a wall and then slowly slide off of it. You will see that the huge skinwidth holds you a long distance from the wall at first, but that this distance gets shallower as you turn. At extremes, this causes the stuck problem.
      I am not sure why the problem does not manifest in this video. My best guess is it's a difference between stock unity physics and Unity's entity physics implementation. My guess is most other engines will also present the problem as I experienced it. My solution to the problem is this:
      Rather than increasing our cast distance by skinwidth and subtracting it off the end, we cast along velocity directly. Then, if an impact is detected, we calculate snapToSurface a bit differently:
      float3 snapToSurface = (math.normalize(vel) * (hitDistance)) + (hit.SurfaceNormal*skin);
      This performs the same separation job, but relative to the wall normal rather than the character's velocity. One thing to note though is that you should probably scale your skinwidth with the magnitude of velocity when using this approach, otherwise you may bounce off the wall due to a skin width result that exceeds the velocity pushing you into the wall. You could also simply use a value of skinwidth that will always be less than the minimum velocity that could be applied.

  • @Banaaani
    @Banaaani Год назад +18

    I have roughly 5 years of pretty much daily experience with Unity and C#, and I still learned a lot in this video. Awesome stuff!

  • @FractalWanderer
    @FractalWanderer Год назад +5

    Dude, this is THE most underrated channel I've ever seen. Top notch content, will be using this, and I subscribed

  • @thewowo
    @thewowo Год назад +9

    Finally! Someone who understands my frustration with character controllers. Lack of interpolation between fixed update steps in the built-in one is by far the biggest drawback for me.
    Great video! I've never considered a recursive approach, I always go iterative.

  • @Saidriak
    @Saidriak Год назад +1

    So glad someone answers this question properly, a year or two ago I couldn’t find any help on the matter and came up with my own hacky but functional solutions

  • @jamesclark2663
    @jamesclark2663 Год назад +6

    I've written many many character controllers over the years and this one is pretty top quality for how simple it is. In fact, it solves an issue I currently have which is that the controller I designed for my player is very fully featured but a bit too heavy-weight to use at scale. However, I needed a character controller that functioned similarly for NPCs. This little function saved me at least a day of tearing out chunks of some of my own controllers to get something that functioned well and was still resonably performance. Great video!

    • @ReimsForYou
      @ReimsForYou Год назад +1

      And could you explain to me some things (I'm just a beginner, and in some places I may not understand). Does everything work purely on colliders, without using RidgedBody? I also didn’t understand where he got the variable "bounds" and "layerMask". I will be very grateful)

    • @jamesclark2663
      @jamesclark2663 Год назад

      @@ReimsForYou Yeah, there are a few minor things like I noticed too. The bounds are obtained from the collider(s) you would be using for your character - in most cases a single sphere or capsule, though in theory you could also use extend the bounds to include multiple colliders. In my case I'll probably go with a public Collider field in the MonoBehaviour that allows me to pass a reference to that collider. Then in Awake() I'll calculate the bounds and extend it by the skinWidth (the code for that is shown very early in the video). Then you can simply assign 'bounds' to 'MyCollider.bounds' within the CollideAndSlide function and it should just work. 'layerMask' is a similar deal. Just make it a public field and then you can assign whatever layers you want in the inspector. This code appears to move this object via its transform which implies that the collider would be a trigger and there would be no rigidbody attached. Likely in my case I'll end up attaching a rigidbody, marking it as kinematic, and keeping the collider as-is rather than making it a trigger and then moving the object via the Rigidbody's position value instead since I'll be needing physical interactions such as pushing other things around. Also, turning off the grabity for the rigidbody would be a good idea if you intend to use the built-in gravity this example provides.

    • @kingbling7571
      @kingbling7571 Год назад

      ​@@ReimsForYou he has a collider on the body (sphere collider in this eg). The collider has a variable called bounds you can access from collider.bounds as shown in the video. It is there for the Sphere Cast. As for layermask, you can set a specific layer for collision check when sphere casting say you want to check if your character is only colliding with a specific layer eg. Layer 8 ur layer mask value will be 2

  • @jaredm5735
    @jaredm5735 25 дней назад

    good stuff, used this for a lightweight 2d ECS character controller

  • @jannagilleman4101
    @jannagilleman4101 Год назад +72

    here before this blows up

  • @TacoTechnica
    @TacoTechnica Год назад +6

    Yes! Thank you for helping more game devs break out of their rigidbody crutches!

  • @baldmanevil
    @baldmanevil 3 месяца назад +2

    great help. I managed to recreate exactly this in Unreal, using Blueprint. Works great for having the camera slide at the edge of the map in an RTS game

  • @gftk5566
    @gftk5566 Год назад +1

    Underrated. I see this is the first video in this channel so, no hopes are gone. Expect to pop off!

  • @FuranA7x
    @FuranA7x 3 месяца назад +1

    I've been trying for months to create a 3d engine on my own and came almost with the same conclusions as this video, but with some exceptions. I'll borrow some things I've missed and if it works you'll have my eternal gratitude :D

  • @jadephoenix5837
    @jadephoenix5837 Год назад +2

    Arguably one of the most well presented tutorials Ive ever seen. Fantastic job!

  • @KronugiN
    @KronugiN 10 месяцев назад

    This is exactly the thing I was working on myself and came as close as a hair's width to figuring out before switching to simply using velocity-based rigidbody controller. I didn't go as deep as reading an actual SCIENCE PAPER, though. Have been waiting for a continuation of this for quite a while and if you're still going to do this - it'd be incredibly interesting to see how you would solve stairs and slopes in a controller like this. Cheers!

  • @evehaddox
    @evehaddox 3 месяца назад +1

    Thanks, this made my movemant way better

  • @iHeartGameDev
    @iHeartGameDev Год назад +4

    Awesome video! Welcome to RUclips! Subbed 💛

  • @yaafl817
    @yaafl817 11 месяцев назад

    I remember searching for this when first studying game dev years ago, it was incredibly infuriating the amount of trash replies you'd find. Thanks for this, I wish this video was around when I first started

  • @catfree
    @catfree Год назад

    I like how this video teaches you why it does instead of only how it does

  • @1ballad
    @1ballad Год назад +2

    nice video, this is probably gonna get boosted by the algorithm

  • @mementomori7160
    @mementomori7160 Год назад +1

    It's funny how I tried to make a character controler on my own quite a while ago and was smart enough to came up with this, but stupid(inexperienced) enough to fuck up when coding it, your vid makes me want to come back to that project and try again

  • @andremarques4063
    @andremarques4063 Год назад +2

    Poke Dev, you are amazing. Poke Dev please continue posting videos.
    Just writing your name so the algorithm can push you up. Damm, this video was amazing. From the editing to the content, it was so nice to watch I was thinking I was watching a Million subscribers youtube channel.
    Keep it up and you are going to make it far!

  • @Splatball
    @Splatball Год назад +3

    Well well well if it isn't the exact video I was attempting to find two months ago. I'm pretty sure normalizing the redirected vector and multplying by the magnitude is the piece I was missing and looking for someone to tell me.
    Nice job on this video, it's high quality.

    • @poke_gamedev
      @poke_gamedev  Год назад +1

      Yes, there was shockingly little info about it online! When I found Fauerby's paper I knew I had to make a video.

    • @Splatball
      @Splatball Год назад +1

      @@poke_gamedev Something you might want to consider in future content is that parameters like "gravityPass" both presuppose that the game will have gravity and don't adequately explain what the effect of that parameter is. It requires the reader to fully read the method body before being able to use the method which is not always what you want from a premade solution. Something like "shouldSlideOnSlopes" might be easier to use.

    • @poke_gamedev
      @poke_gamedev  Год назад +1

      I agree it could be more descriptive, however the way I wrote the function was as a private method to be called inside a larger character controller class. So in my case, someone using the character controller class wouldn't have any reason (beyond curiosity) to know the exact implementation for collision, as this method wouldn't even be exposed to them.

    • @Zicrus
      @Zicrus Год назад +4

      NO, please don't do that part! It doesn't make any sense to normalize and rescale it, and just leads to the problem at 8:50. That part in the video is just wrong, so please don't copy it. In real life it does lose magnitude, so it is not a problem.

  • @davidmc971
    @davidmc971 Год назад +1

    Really nice overview! Even though I would personally keep the velocity decrease on hitting an edge instead of decreasing later on. Saw your pinned comment on this too. Thank you!

  • @thatperson9478
    @thatperson9478 Год назад +14

    hit and run? nah, I prefer collide and slide.

  • @BulletsToBrainRatio
    @BulletsToBrainRatio Год назад

    Thank you so much! I was looking for a solution when I was working on my own movement controller, and adding a speed boost would thrust me through geometry.

  • @theashbot4097
    @theashbot4097 Год назад +4

    I was making a custom physics engine for unity. I gave up on it because the collisions and the slopes just did not work. I did not delete the code just in case I needed part of it because I added a lot to it. I saw this video and I was like "Hmm this looks interesting." so I watched it then I added the code to my project, and it did not work. the reason why is because I had the old code and this new code running at the same time. but I got it to work after about 30 min of trying. THANK YOU! for the video!

    • @clonkex
      @clonkex Год назад

      "did not delete the code" if you're not using version control, you should be. Seriously, it's worth the pain of learning (and actually with GitHub Desktop it's not even much pain)

  • @daytonode
    @daytonode Год назад +4

    I was toying around with this a while back but I was having a miserable time finding good sources of information for it, as comprehensive as this anyway. How are you able to find all this information so easily? I even consider myself pretty good at googling.

  • @t-ree
    @t-ree Год назад +2

    Well done btw this video will blow up soon so remember me when you become famous ❤!

  • @MattSimon1
    @MattSimon1 6 месяцев назад +1

    The presentation is awesome. I wish I was just a bit smarter and understood this. Maybe one day.

  • @РексДинозавр-ж3л
    @РексДинозавр-ж3л 5 месяцев назад +1

    Thanks bro for the link to the material, it helped me a lot.

  • @simonsvoboda8849
    @simonsvoboda8849 Год назад +1

    Right on time. I was just doing collisions today (for my game-engine-less game). Guess I'll be rewriting it tomorrow after watching this video lol. Anyways, this is just what I was looking for and couldn't find. Thanks!

  • @electroncat
    @electroncat Год назад +2

    194 Subs? How, this has great video quality.

  • @moonyarwick8222
    @moonyarwick8222 Месяц назад

    To anyone who tries to implement this using a box collider:
    Don't divide the algorithm up into horizontal and vertical passes if you plan to have sloped floors in your game. Doing this will occasionally "miss" a collision detection and pass the player straight through floors.
    My solution to this problem was to only use one "pass" with the entire velocity vector, not separated into horizontal and vertical passes. And if the floor was angled within a walkable steepness, I would set the leftover vector3's y value to 0. This will stop the player from slowly sliding down slopes that he should be able to walk on, but would still slide him down along a steep wall.

  • @zetty8977
    @zetty8977 Год назад +1

    The only video to appear on the subject that actually looks at the real problem, and everything you showed us in this video is exactly what I came to as a conclusion in my own testing over the past 2 years back and forth.
    Everyone else, just says use Rigidbodies or the built-in char controller, as you clearly showed as well.
    I have a slight different approach to mine, but the resulting vectors and movment is exacly the same, besides some trigonometry approaches to corner collisions.
    Another slight issue I have found with this, using raycasts, is that it more often than not sets itself inside the geometry of the world, thus the raycast does not report any hits for that collider. But I guess that the skin width solves that problem fairly okay-ish.

  • @paomiank9796
    @paomiank9796 Год назад +3

    Thank you bro, your video is really helpful and easy to understand.

  • @3d_eric
    @3d_eric 6 месяцев назад +1

    Great explaination! With the help of your video i implemented the algorithm in a custom godot character controller. Right now i only use a raycast, but i will transfer the logic to shape casts, which is the equivalent of the sphere cast in unity.

    • @poke_gamedev
      @poke_gamedev  2 месяца назад +1

      Awesome! Godot actually has a lot of this functionality built-in to its CharacterBody3D class (move_and_slide(), or something), which is what I would start with if I were to make the switch :)

    • @3d_eric
      @3d_eric 2 месяца назад

      @@poke_gamedev in the end I went with the built in move and slide function. It got me very far into the controller without many adjustments. I use it for a skateboarding game.

  • @jzeltman
    @jzeltman Год назад +2

    great explanation

  • @LeftoverAtoms
    @LeftoverAtoms Год назад +2

    This was life changing 😮

  • @lorz9442
    @lorz9442 Год назад

    The explanations and production value of this video is off the charts! Awesome video :) thanks

  • @anda9169
    @anda9169 Год назад +1

    Truly underrated

  • @MinibossMakaque
    @MinibossMakaque Год назад +1

    Oh my god, why couldnt this video have existed years ago? As someone who tends to become obsessed with doing things the "correct" way, every time I've gone to make a game I get a bit of the initial setup done, then get fixated on the character controller for weeks, unhappy with most of what I see online.

    • @poke_gamedev
      @poke_gamedev  Год назад +2

      Yeah I've gotten stuck in the character controller rabbit hole like 5 times now lol

  • @dvzdev
    @dvzdev Год назад

    This is incredible video quality! Needs to be seen by more people, hope you get the attrntion you deserve

  • @Wishbone_Games
    @Wishbone_Games Год назад

    Man this is such a well made video, genuinely got better quality than me-whos been doing yt for a year, on your 2nd video????? You are going places

  • @SinstixMain
    @SinstixMain 8 месяцев назад +1

    I'm quite late to this but there is an issue with your implementation, in the sphere cast params, you should put the original velocity as the direction not the normalized version of it, this is to ensure that the cast covers the full distance you'll cover in that same frame, this is needed when moving at higher velocities so you don't tunnel into walls.
    Other than that, this video is amazing, I'm currently working on my collision handler for my character controller and this helped tremendously, can't thank you enough ♥

  • @falconegaming
    @falconegaming 11 месяцев назад

    I can't seem to figure out why it drags going uphill at times, but the video taught me a lot.

  • @K9Megahertz
    @K9Megahertz 10 месяцев назад

    I think Kasper's stuff was inspired by Paul Nettle's stuff (actually, it was, just checked the references in Kasper's doc). I remember this stuff back then, did an implementation of it myself. I seem to recall one of the problems with Paul Nettle's implementation (and perhaps Kasper's original implementation) was that clipping the side of a ramp at a very shallow angle would clip through/get stuck. Imagine you wanted to go straight up the ramp was off to one side too far and just missed it. It's been 20+ years, so things may be a little fuzzy.
    I never followed through with an implementation of the improved version.
    I'll probably dig back into this topic again in the near future.

  • @notbillymays
    @notbillymays Год назад +2

    how does this have barely attention bro, this vid is extremely useful

    • @KaitouKaiju
      @KaitouKaiju Год назад

      It's not exactly a light watch

  • @Not8bou3
    @Not8bou3 Год назад +4

    I just started working on my physics engine, thank you for this great explanation!

    • @poke_gamedev
      @poke_gamedev  Год назад +3

      Glad it was helpful!

    • @Zicrus
      @Zicrus Год назад +2

      A small thing to keep in mind if you want to use this for a more general physics engine, is that the thing at 4:04 where they rescaled the vector is not physically accurate. You should just leave it as is with the shorter length. Then you also don't need to do what they did at 8:50, which they only did to compensate for the rescaling earlier.
      Those things in the video really only apply to character physics specifically, since it handles walking up or down slopes inaccurately, which feels better in some situations.

    • @Not8bou3
      @Not8bou3 Год назад

      @@Zicrus
      yeah thanks, This will only be helpful for CharacterBody and KinematicBody structures. I should make a move and slide function for them to make it easier for game devs. But for other physical structures like RigidBody I’m using more accurate approaches for collision responses.

  • @nokkturnaldev
    @nokkturnaldev Год назад +2

    Absolutely fantastic! Please keep making videos.

  • @the-guy-beyond-the-socket
    @the-guy-beyond-the-socket Год назад +1

    Critically underrated

  • @fruitfunfitness3584
    @fruitfunfitness3584 Год назад +9

    Instead of scaling the projected vector to be the same magnitude as the leftover velocity, and then scaling it again based on the angle to the perpendicular, can we not just use the projected vector as is? Will the projected vector naturally contain the desired perpendicular component if we wish to slow down our character? I've not implemented this myself yet, so it's a genuine question. Thanks.

    • @DrazkurHW
      @DrazkurHW Год назад

      this was my thought. I haven't done the math but i believe it would give the same result and he's just taking an extra step for no reason. Although you could make the case that once you have the vector normalized you can tweak the on-wall velocity to your liking

  • @ddoober
    @ddoober Год назад +1

    THANK YOU SO MUCH

  • @pinuss
    @pinuss 11 месяцев назад +2

    Something is off. I followed the tutorial thoroughly and tried implementing the algorithm for a capsule shaped character. Collisions were fine on the surface, but when I had the character collide with tent shaped geometry (two stretched boxes tilting toward each other, and oriented so that the further inside you go, the lower the ceiling is), it started clipping through the tent, unless you head into the tent straight on. any horizontal movement is going to cause clipping. I figures it is with the skinWidth doing some goofy stuff like pushing the player away from the colliding object when the object is inside the skinWidth. can anyone help?
    Edit: Another thing that may proves this has something to do with skinWidth is when I set the skinWidth to something like 0.45f, then move at an angle that is almost paralel to the surface, instead of the moving the character a skinWidth distance away from the wall, it just slowly inches towards the wall, until it the distance between player and wall reaches the radius of the capsule cast (aka capsuleRadius - skinWidth), as if "snapDist = hit.distance - skinWidth" have very little effect. When looking and moving at the wall at an angle almost perpendicular, this behavior doesn't happen}
    Edit 2: Found out the hard way that just doing "snapDist = hit.distance - skinWidth" isn't correct at all. the closer to getting perpendicular to the surface's normal, the more you'd have to subtract from hit.distance. so here's the proposed solution:
    float bigHypotenuse = capsuleRadius / Mathf.Sin((90 - Vector3.Angle(hit.normal, -vel.normalized)) * Mathf.Deg2Rad);
    float smallHypotenuse = (capsuleRadius - skinWidth) / Mathf.Sin((90 - Vector3.Angle(hit.normal, -vel.normalized)) * Mathf.Deg2Rad);
    Vector3 snapToSurface = vel.normalized * (hit.distance - (bigHypotenuse - smallHypotenuse));
    where as bigHypotenuse is the length between the big capsule center (aka the capsule without any skinWidth) at the position where it is contacting the hit point, and the point where the velocity would hit if raycasted (very much oversimplified, my wording is very off). smallHypotenuse is the same but for the capsule with its radius - skinWidth.
    for some reason this would create jittering if skinWidth is too high, so if the whole purpose of skinWidth is to stop floating point inaccuracy, then setting it real small (like 0.0001f) would work. still could'nt figure out why it is jittery though.
    this solution still isn't perfect however, because the collider can still clip through the walls. I suspect this is because my implementation only work on the XZ plane, since I tried sketching it at a top down view
    private Vector3 CollideAndSlide(Vector3 pos, Vector3 vel, int depth, bool gravityPass)
    {
    if (depth > maxBounces)
    {
    return Vector3.zero;
    }
    if (vel.magnitude < minMoveDistance)
    {
    return Vector3.zero;
    }
    Vector3 botCenter = pos + transform.up * capsuleRadius;
    Vector3 topCenter = pos + transform.up * (capsuleHeight - capsuleRadius);
    float dist = vel.magnitude + skinWidth;
    RaycastHit hit;
    if (Physics.CapsuleCast(botCenter, topCenter, capsuleRadius - skinWidth, vel.normalized, out hit, dist, collidingLayers))
    {
    float snapDist = hit.distance - skinWidth;
    Vector3 snapToSurface = vel.normalized * snapDist;
    Vector3 leftover = vel - snapToSurface;
    leftover = Vector3.ProjectOnPlane(leftover, hit.normal);
    return snapToSurface + CollideAndSlide(pos + snapToSurface, leftover, depth + 1, gravityPass);
    }
    return vel;
    }

  • @discordsucks7061
    @discordsucks7061 4 месяца назад +1

    my goat

  • @SamuelPollack-f7j
    @SamuelPollack-f7j 4 месяца назад +1

    this should be very helpful for my botw inspired controller

  • @duncanstanway3463
    @duncanstanway3463 10 дней назад

    Amazing! Thank you!

  • @ruzgar1372
    @ruzgar1372 5 месяцев назад +1

    4:10 Why scale the projected vector up, if we're just gonna scale it down (based on the angle) anyway? If you leave the code there, it should be so that the straighter you go into the wall, the slower you move which is what we want.

  • @lucasmontec
    @lucasmontec Год назад +1

    If you just keep the projection of the velocity on the plane, without normalizing and scaling, you'll have a velocity that automatically increases with the angle of the plane to the velocity...

  • @ccl1195
    @ccl1195 Год назад +1

    I appreciate your approach and also your general calling out of the people so quick to act as if they know what they're talking about, all across Unity. For as many people as you mention, there are plenty of little "script-bros" who will yell "lol don't use rigidbody at all!" when you ask for help with your dynamic rigidbody player controller. When you ask them why, you usually hear something like "lol I don't even use the physics system much."
    Anyway, I was wondering if you have any helpful information about crushing that horrible, classic "Unity jitter" when using a first person dynamic rigidbody controller. I've come a long way with mine, but it's by no means perfect. "lol just interpolate the rigidbody bro" is not something that "just works." I've done a few different things along the way, but I'd like to know if you have helpful insights around this, or would like to make a video on it if you do.
    Thanks.

  • @goodboi42
    @goodboi42 Год назад +1

    Fantastic video and explanation.

  • @CreateGamez-tr4el
    @CreateGamez-tr4el Год назад

    Exactly the Kinematic Character Controller, the one i'm using in my game, it's too complicated, but im trying my best to understand it

  • @Barldon
    @Barldon Год назад +4

    The 'just use a dynamic rigid body' thing gets on my nerves too. Outside of all the reasons you wouldn't want to do that, number one is that applying forces directly through the physics system in order to code a character movement system is just so wrong and no matter which way you do it is going to end up being unintuitive in one way or another.
    I find the built in character controller to be 'fine' for my use cases, but a custom kinematic controller is undoubtedly the best and most flexible way to go about it (After all, I assume the built in controller is very similar to a kinematic controller behind the scenes). As far as I'm aware, that would be how it is done in a larger studio, and how it has been done in general for decades.

    • @poke_gamedev
      @poke_gamedev  Год назад +2

      Yeah, relying on the physics system with forces, friction, dampening, etc, for core mechanics like character movement has always given me "trying to drive a car by pushing it from behind" vibes. Not at all intuitive and certainly less predictable/reliable.

    • @FakeGuthix01
      @FakeGuthix01 Год назад

      How is using a rigid body and moving it through forces unintuitive? It's literally how things move in real life. Now there are a few "cheats" we need to use to make the physics respond the way players expect them to *feel* because Unity's physics engine is limited in fidelity, namely disabling gravity when grounded (basically assuming the normal force of the ground perfectly
      counter gravity ) and disabling friction when the player is giving movement input (assuming that kinetic friction is so low it might as well be 0). But otherwise I have found the rigidbody system to be fine for implementing Quake style movement that is used in countless first person games.
      Not trying to argue. I'm genuinely curious as to your reasons.

    • @Barldon
      @Barldon Год назад +1

      @@FakeGuthix01 Nah I get it dw, it's all opinion too. To me it's unintuitive because it's not precise, I'm just giving it a force rather than actually controlling it's velocity precisely. When I'm designing something that needs to be as precise as a character controller, I want to work with the exact values rather than just applying forces and trying to feel out what's right. From a fundamental level, controlled movement is also not what physics rigidbody's are designed for (Hence why they provide the built in character controller to begin with), which causes additional issues. When you have to give your character spring-based floating to work around the issues of rigidbody's, you're fighting against the system that's not designed to do what you're asking it to do. And hey, if it works for you or if in your specific situation that's what you want and works better than other options then more power to you, everything unity offers is a tool you can choose how to use. I just think it's not great general advice to give to people.

    • @poke_gamedev
      @poke_gamedev  Год назад +2

      If you want your character to move at 5m/s, you could apply a force of ~5, figure out which ForceMode is correct, then realize you never actually reach top speed due to friction, then you want to change how fast you accelerate without changing the top speed, then you realize that instantaneous movement is basically impossible without completely mangling the physics material and rigidbody properties, etc, etc. And then at the end you still might not be moving at exactly 5m/s...
      Or you could go kinematic and just have a 'moveSpeed' variable with a value of 5 and it just works and you don't have to screw around endlessly with the physics system. You even mentioned workarounds in your question that could be avoided by using kinematic instead. Add in things like jumping, wall sliding, ledge grabbing, etc, and you eventually have a tangled mess of those physics system workarounds that could be accomplished easier without using the physics system at all.

  • @CamrunThomas
    @CamrunThomas Год назад +2

    Very good i like this alot

  • @saniel2748
    @saniel2748 Год назад

    That's a good explanation. Though when I tried to implement this a year ago I eventually gave up and replaced my own solution with Kinematic Controller asset which became free, convenietly
    It really gets just so much more darn complicated when you start working with stairs, slopes and edge cases. Maintaining "skin width" is probably the most annoying part as PhysX won't correctly do CapsuleCast if you already touch the wall, so you have to maintain little distance

  • @LlocoGames
    @LlocoGames Год назад +2

    Great video

  • @lore3212
    @lore3212 10 месяцев назад

    AWESOME!!!
    It would be really great if you would upload a sample project so that I (or others) can analyze the code and understand it better
    Tomorrow i will try to implements this in my characterController! Thank you

  • @tianqigao869
    @tianqigao869 Год назад +1

    awesome!

  • @vitorcedrim6804
    @vitorcedrim6804 Год назад

    Thanks for the high quality content, keep going!!

  • @T0MA5
    @T0MA5 Год назад

    would love to see more videos like this

  • @tdif3197
    @tdif3197 Год назад

    This is a great video, but i gotta say the way you formatted your spherecast conditional lines is pretty insane haha

  • @a1534-d7k
    @a1534-d7k Год назад

    THIS IS AWESOME

  • @arfa8
    @arfa8 2 месяца назад +1

    I‘m really new to unity and also like to search for the perfect player controller,but I habe a few questions(sry if they‘re maybe stupid, like i said im new to unity: do you makw basic movement for the player with a rb and addForce() or another way to add velocity, and if not how do u do it then? And basic collisions with the ground, are they also managed with a rb? Thanks already and this is a really cool vid!

  • @tonylazuto9001
    @tonylazuto9001 Год назад +1

    This is good, and I tend to use similar techniques when writing CCs, but the big issue I always face is the collision detection, i.e. the spherecast. Specifically, if any geometry is inside the origin sphere at all, it will return messed up sphere hits for that collision. So if the character ends up clipping into anything, it won't be able to push itself back out correctly. I really need a way to get info about surfaces inside a given sphere. You can use an overlap sphere and then closestpoint on colliders, but it doesn't work with concave mesh colliders.

    • @poke_gamedev
      @poke_gamedev  Год назад

      I've only been able to find one edge-case so far where the collider can clip into a surface. But yeah, it is currently missing the ability to push out of overlapping objects.

    • @KelseyHigham
      @KelseyHigham Год назад

      i test every position for collision before moving the player there. if the player starts a frame colliding, then they spawned inside a collider, and i allow them to fall through the floor until they start a frame *not* colliding.

  • @gdalchemy
    @gdalchemy Год назад +2

    Love this. Super useful 💪🏽

  • @matt64bit
    @matt64bit Год назад

    Thanks for explaining the basics, I tried tackling this problem on my own but got stuck at the response, the character either stopped too far from the wall leaving a visible gap or for some reason completely passed through it, thanks for the video

  • @buu_mm6784
    @buu_mm6784 Год назад +1

    very nice

  • @monkeydgoofy8074
    @monkeydgoofy8074 Год назад +1

    aight man your amazing video earned you a new subscriber

  • @andersama2215
    @andersama2215 Год назад +1

    Probably want to stick with the iterative approach over the recursive one to make better sense of what mathematical operations you're doing to calculate what you need. While recursion's nice to deal with recursive problems, this is fairly trivial simple algorithm which is easy to transform without recursion. The calculation should naturally terminate anyway assuming your floats or doubles aren't infinite. Removing recursion here can be easily done with a temporary and a check that the new "slide" is or is not a collision. There's just not much reason to use recursion here. It may make more sense to use the "bounces" when the floats are infinite to make sure you can't have an infinite loop (a stack overflow from recursion that terminates an infinite case may be an ok thing for this reason).

    • @poke_gamedev
      @poke_gamedev  Год назад +1

      I'm working on implementing stairs for the next video and ended up coming to this same conclusion. Recursion was nice when it was *just* collision, but got completely out of hand as I started adding exceptions and features on top of it. So now I've started over, using the improved algorithm from the 2nd paper as a base.

  • @322ss
    @322ss Год назад

    Thanks! Editing must have taken a good while - neat visualizations.

  • @BarcelonaMove
    @BarcelonaMove 6 месяцев назад +1

    This shit is real, keep it coming!

  • @Splarkszter
    @Splarkszter Год назад +1

    Ypur work is incredibly good!, thakn you so much for leaving this piece of education for free!!!
    Sadly unity became a greedy mess. R.I.P.

  • @xEweman
    @xEweman Год назад +2

    Awesome video man, mind telling me (or someone who knows) what do you use to create the animated slides and graphics?? Thanks!

    • @poke_gamedev
      @poke_gamedev  Год назад +1

      I used Motion Canvas!
      motioncanvas.io/

  • @h4ngman
    @h4ngman 2 месяца назад

    Holy shit, looks like I've come up with collide and slide on my own when trying to improve on a basic character controller tutorial that didn't do what I wanted. Originally I just wanted a wall slide effect but in the end I arrived pretty much exactly here. It felt like nothing special when I wrote it, I totally dismissed it as probably a bad solution since it wasn't in the tutorial but someone else based a paper on this. Huh.

  • @kiekiestudios
    @kiekiestudios Год назад

    you dont need to acount for the direction your facing to slow your speed on a wall you could just leave the progected vector alone and not scale by the distance of the removed vector to get a very similar result

  • @willlogs
    @willlogs Год назад +1

    Good video. Keep it up brother.

  • @rehnquisteaeoauycbgcwa8763
    @rehnquisteaeoauycbgcwa8763 8 месяцев назад

    Hey! I just wanted to mention that there is a small bug with this implementation. When moving into corners, the player can end up passing through because the check to make sure SnapToSurface is more than SkinWidth doesn't take into account the angle in which the player is moving into the obstacle, so sometimes the player ends up inside the skinwidth distance from a wall, letting them pass through. I fixed this by changing the code to:
    Vector3 SnapToSurface = Vel.normalized * (hit.distance + SkinWidth / Mathf.Cos(Vector3.Angle(Vel, hit.normal) * Mathf.PI / 180));
    *Edit: As it turned out, this only fixed being able to climb up corners, clipping through corners by jumping and moving forwards still exists. If anyone knows a fix, that would be much appreciated.

  • @Btmodz
    @Btmodz Год назад +1

    good video

  • @auraxarr
    @auraxarr 10 месяцев назад

    Incredible video, mister Poke, thanks a lot for helping me with dealing with the wall Im bashing against last half a year :) A thing that looks unclear to me - at 07:48 you showed your test sphere moving down at any slope but how is that possible by that moment without gravity checks applied yet? In my backpedalling case my capsule just floats in the air which is fine to my opinion because I (as well as you in the video) only apply XZ movement :) thanks again!