Poke Dev

Poke Dev

I make videos about game dev sometimes. My main channel is @poke_

Пікірлер

  • @user-vi4md7px5j
    @user-vi4md7px5j8 күн бұрын

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

  • @pruttisman
    @pruttisman9 күн бұрын

    Fairly inexperienced programmer here! This is an excellent tutorial, but I'm running into an issue where my character gradually slows down to a crawl when heading toward an obstacle, only to pick up speed and slide correctly once the collision occurs. I think it might be related to snapToSurface, as this value decreases along with the character's speed, but I can't really wrap my head around what's going on. Anyone have any ideas?

  • @brichearnaud5314
    @brichearnaud531412 күн бұрын

    I do have a genuine question: Why are you using _bounds.extents.x in your sphere/capsule cast for the radius ? Extents are world oriented in Unity, meaning that depending on the orientation of your collider (either dynamically or on start), you would get different values ? Amazing content nonetheless, thank you very much for this video!

  • @ligazetom
    @ligazetom17 күн бұрын

    Regarding the preserving of speed independently of collision normal, is the dot product needed? Shouldn't the projection on the plane already take care of that.

  • @3d_eric
    @3d_ericАй бұрын

    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.

  • @BarcelonaMove
    @BarcelonaMoveАй бұрын

    This shit is real, keep it coming!

  • @MattSimon1
    @MattSimon1Ай бұрын

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

  • @JKczolg
    @JKczolgАй бұрын

    will you make a second one by anychance?

  • @Krashevil
    @Krashevil2 ай бұрын

    at 11:23 when you are walking over the green edges, my object clips through the ground. im not sure why. i didnt make any mistakes copying the implementation. can you provide the source code for this scene?

  • @Krashevil
    @Krashevil2 ай бұрын

    I hate RIgidBody and CharacterController with a passion

  • @TheVonWeasel
    @TheVonWeasel2 ай бұрын

    <insert xkcd "competing standards" meme here>

  • @thisisarbaz
    @thisisarbaz2 ай бұрын

    Can you share the git or project file?

  • @decofox6789
    @decofox67892 ай бұрын

    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
    @decofox67892 ай бұрын

    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.

  • @appleseedgames6934
    @appleseedgames69343 ай бұрын

    Good work, you've just redesigned a rigidbody from the ground up...

  • @Blazs0
    @Blazs03 ай бұрын

    I'm having a terrible time getting this code to compile with a bunch of errors... Im no coder though :(

  • @digitalpanda5969
    @digitalpanda59693 ай бұрын

    Root motion

  • @rehnquisteaeoauycbgcwa8763
    @rehnquisteaeoauycbgcwa87633 ай бұрын

    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.

  • @growguru2020
    @growguru20203 ай бұрын

    iam not sure if iam do anything wrong but that dont work for me :( the player dont move...if i put the rigidbody to him then he fall from the terrain... idk if i do anything wrong :(

  • @Absence_of_Light
    @Absence_of_Light3 ай бұрын

    I encountered a bug where the character would accelerate upon collision with a wall instead of scaling the vector down. My solution was to not normalize the 'leftover' vector in the: if (isGrounded && !gravityPass) { } code block. I'm not a math expert, so I could be mistaken but I found it a bit odd that we normalize the 'leftover' vector inside the mentioned code block, but not outside of it. It seems redundant, especially considering that we already normalize it within the 'ProjectAndScale()' function. However, a thorough review of the documentation or consulting with someone more knowledgeable could provide clarity on this matter. PS: Instead of the 'Physics.SphereCast();' I am using the 'Physics.CapsuleCast();' calculating the point1 and point2 positions as follows: Bounds colliderBounds = m_Collider.bounds; Vector3 p1 = colliderBounds.center + Vector3.up * -m_Collider.height * 0.5f; Vector3 p2 = p1 + Vector3.up * m_Collider.height; PS 2: Leaving this comment in hopes that will help someone encountering the same bug.

  • @SinstixMain
    @SinstixMain3 ай бұрын

    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 ♥

  • @javac9158
    @javac91583 ай бұрын

    The collider starts to feel floaty when approaching a collision. Wanting to start floating before hitting the ramp and softly landing when falling off things. Should be able to smack full force into a wall if the player so chooses but instead it's a small cushion that it he runs into. How do I solve this?

  • @KronugiN
    @KronugiN4 ай бұрын

    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!

  • @K9Megahertz
    @K9Megahertz4 ай бұрын

    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.

  • @ShellSharpInc.
    @ShellSharpInc.5 ай бұрын

    Thank you for this, I have been trying to figure out how to make a good character controller from scratch that I actually understand. One question though, how do you determine the `isGrounded` variable?

  • @n0name249
    @n0name2494 ай бұрын

    do you figured it out? I also find it troublesome.

  • @emiledjidag3091
    @emiledjidag30912 ай бұрын

    @@n0name249 for anyone wondering how to achieve this, personally I added an empty game Object at the bottom of the player and use Physics.CheckSphere to detect collision and determine if the player is grounded or not. A Simple raycast pointing downward at a certain distance might also do the trick.

  • @hldfgjsjbd
    @hldfgjsjbd5 ай бұрын

    But what if player is controlled by adding force to rigidbody? How can we adapt this code?

  • @poke_gamedev
    @poke_gamedev5 ай бұрын

    Forces only apply to dynamic rigidbodies, in which case the collision would be handled by the physics system. This method is for kinematic rigidbodies (or fully custom implementations) that don't use the physics system for movement.

  • @fabianf.2300
    @fabianf.23005 ай бұрын

    Hi, I wholeheartedly tried to implement this into unreal engine with my player character. I am at a bit of a dead end here, haha! If anyone knows some papers or tutorials in that regard, or even better, did it themselves, let me know!

  • @poke_gamedev
    @poke_gamedev5 ай бұрын

    Unreal Engine already has an incredibly robust built-in character controller that handles all this stuff (and more) automatically. It also supports stuff like network replication out of the box, and many existing systems within the engine are designed to work with the default character class. As far as I know, there is absolutely no reason to try and make your own controller from scratch in Unreal.

  • @fabianf.2300
    @fabianf.23005 ай бұрын

    @@poke_gamedev Thank you for the response! I've been trying for a few days as of now but since you mention that these things can be replicated with the already built in system, I've been trying that but unreal does not have any way of making the character slide donwards slopes that can be countered by the added walking velocity.

  • @lore3212
    @lore32125 ай бұрын

    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

  • @auraxarr
    @auraxarr5 ай бұрын

    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!

  • @yaafl817
    @yaafl8175 ай бұрын

    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

  • @falconegaming
    @falconegaming6 ай бұрын

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

  • @ToastaToast
    @ToastaToast6 ай бұрын

    I've was bashing my head against this problem. How did you find these papers? I clearly need to work on my research skills! :o Edit: Usually when I google it, I find the youtube video tutorials or stack exchange post or something equally unhelpful as you described. I never would've known how to find an academic paper on the matter.

  • @x8c8r
    @x8c8r6 ай бұрын

    hey, i tried to use this, and when i tried to add the jump, the player would very slowly glide towards ground before landing

  • @pinuss
    @pinuss6 ай бұрын

    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; }

  • @frenzy2036
    @frenzy20366 ай бұрын

    At 11:14 you show the gravity as a second call of CollideAndSlide with a gravity vector but my character falls at a steady rate instead of accelerating, i'm guessing because the y movement is always set back to 0 in the first call of CollideAndSlide. In this example how are you making gravity continue to increase frame after frame?

  • @pu55yEaterr
    @pu55yEaterr6 ай бұрын

    gravity should be increased every frame. There's many ways to do this. If you want to increase the gravity velocity locally (inside this script), just add a way to ground check, if the player is on the ground, increase the gravity (gravity += acceleration * time.Deltatime;), else set the gravity to 0. Or if you don't want to manipulate gravity inside this script, add a parameter to the Move function and that passes in the gravity, then the function signature should be like this "public static Move (Vector3 moveAmount, float gravityVelocity)", then you can update the gravity in another script, passing that updated grav into this function.

  • @Kunfuzzly2
    @Kunfuzzly26 ай бұрын

    Extremely helpful! I've seen the concept a lot before, but never explained so thoroughly. I am having some trouble adapting your code: I changed the SphereCast to CapsuleCast, and I'm moving my characters via RigidBody.MovePosition in FixedUpdate rather than transform.position in Update -- and my enemies are clipping through walls. :( I copied the code letter for letter, and changed "pos" to "p1, p2". In the recursion call, instead of "pos + snapToSurface", I had "p1 + snapToSurface, p2 + snapToSurface." And instead of "bounds.extents.x", I use the capsule's radius. No complaints when using RigidBody.MovePosition with SphereCast. For now, I'm getting CapsuleCast working by using a janky workaround from this thread forum.unity.com/threads/inaccurate-capsulecast.701636/

  • @Dexterowskii
    @Dexterowskii6 ай бұрын

    Looks that quake/half life used same algorithm for movement :)

  • @HenrikMyrhaug
    @HenrikMyrhaug6 ай бұрын

    Shouldn't the sliding vector when being projected onto the surface already have the exact magnitude we want for sliding along a wall? It seems redundant to increase its magnitude just to decrease it again, but I might be misunderstanding.

  • @elihowe
    @elihowe6 ай бұрын

    hes CRACKEd

  • @lind2235
    @lind22356 ай бұрын

    this is so awesome!! im surprised people are already making maps that look as good as or if not, better than valve this fast

  • @elihowe
    @elihowe6 ай бұрын

    big facts

  • @poke_gamedev
    @poke_gamedev6 ай бұрын

    I have way too many projects I'm working on right now, so I'm not sure when the next Unity video will be up. I do have some other stuff planned for this channel though :) In the meantime, if people are interested in learning about Source 2 or CS2 mapping, let me know in the comments! Also, if you end up trying the map, let me know what you think!

  • @ccl1195
    @ccl11957 ай бұрын

    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.

  • @user-sk4fx2tk1x
    @user-sk4fx2tk1x7 ай бұрын

    THIS IS AWESOME

  • @tdif3197
    @tdif31977 ай бұрын

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

  • @Diablokiller999
    @Diablokiller9997 ай бұрын

    How would you implement this together with stairs? Thinking about sweeping the collider up a defined step height and forward 1 + 1/2 the radius of the collider on collision with a wall,, to check if it's a stair and walkable. Didn't try it out yet, but sounds reasonable to me. Any other ideas?

  • @BulletsToBrainRatio
    @BulletsToBrainRatio7 ай бұрын

    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.

  • @Klayperson
    @Klayperson8 ай бұрын

    all my homies use move_and_slide()

  • @neos6997
    @neos69978 ай бұрын

    You can use this for wall running

  • @Saandy_
    @Saandy_8 ай бұрын

    Great stuff!

  • @mementomori7160
    @mementomori71608 ай бұрын

    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

  • @noosetime9423
    @noosetime94238 ай бұрын

    first of all - DO NOT USE the unity built in character controller lol.