ADDENDUM ------------------- As I continue working on my game I will add notes about improvements/mistakes I find to this comment. It will mostly be nitpicky stuff, but I figure it's still good to call that stuff out for those that care. I will add ⭐ to the ones I think are worth your time to address if you followed along, and ⚠ to any outright mistakes/omissions. ⚠ *Generate C# input class* (at 1:29) Later in the video I use the `PlayerInputActions` class generated by the input actions asset created here. The "Generate C# Class" option is not toggled on by default, but it should be enabled and I forgot to mention it. You can see it in the inspector on the right side of the screen at 1:29. *Using LateUpdate to update the camera position is unnecessary* (at 6:04) The character's physics are updated in FixedUpdate() which is called by Unity before Update() is called, so playerCamera.UpdatePosition(...) can safely be called from Update() alongside playerCamera.UpdateRotation(...). *Jump unground time should be >0* (at 13:50) When jumping, the character motor is forcibly ungrounded. I set the unground time to 0 in the video because I didn't think there was any good reason to keep ungrounding the player after they jump. However I later noticed that when jumping up steep slopes, the player would often immediately reground itself, essentially cancelling the jump in a jarring/frustrating way. By setting the unground time to something like 0.1, the player won't reground itself if it hits the ground immediately after jumping which does a better job of respecting player intention. ⚠ *Incorrect Camera Offset* (at 55:17) The "localSpringPosition" is not really local. "Relative" would be a better term since it is the world-space offset between the spring and its target position. Because the `localSpringPosition` is actually a world-space measurement, it should be renamed to `relativeSpringPosition` and **added** to the `transform.position` instead of being **assigned** to the `transform.localPosition`. The effect was subtle enough that I did not catch this until a month later :P ⭐ *Camera Leans Even When Not Moving* (at around 56:32) Camera leaning is based on the acceleration contribution from **moving and sliding.** This acceleration is calculated correctly, but the **final** acceleration of the player can be inhibited by collisions and other factors. Because the acceleration **we** calculate part way through the UpdateVelocity method does not take this into account, the camera can lean very far when walking into a wall even though the player is not actually accelerating. To fix this, you can calculate the total acceleration after the character updates and clamp the magnitude of the movement acceleration we stored in `_state` variable so that it doesn't exceed the total acceleration like so: // PlayerCharacter.cs public void AfterCharacterUpdate(float deltaTime) { // Stuff can happen after move acceleration (walk/slide movement) is applied to current velocity that // *lowers* the velocity, so after the character updates make sure move acceleration does not exceed // the total acceleration. var totalAcceleration = (_state.Velocity - _lastState.Velocity) / deltaTime; _state.Acceleration = Vector3.ClampMagnitude(_state.Acceleration, totalAcceleration.magnitude); ... I'd also recommend projecting the acceleration vector whenever the character hits something while moving: // PlayerCharacter.cs public void OnMovementHit(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint, ref HitStabilityReport hitStabilityReport) { _state.Acceleration = Vector3.ProjectOnPlane(_state.Acceleration, hitNormal); }
@stormburpee85022 ай бұрын
I think I've done this addendum very wrong hahaha... Are we still needing to reset the localPosition when we're adding to the transform.position? My camera ends up trailing the controller over time...
@KeenanWoodall2 ай бұрын
@@stormburpee8502 Yes the transform.localPosition should still be reset before everything else! Then you just do transform.position += relativeSpringPosition * linearDisplacement; instead of transform.localPosition = localSpringPosition * linearDisplacement;
@aymeric-devv27 күн бұрын
Hello, how to change the crouch mode ? Because it's toggle state but can be just when we press crouch key it crouch ? Sorry for my bad english
@Andrashh22 күн бұрын
@@stormburpee8502 If it's still wrong, check if you changed all the *Vector2* from the method to *Vector3*
@Andrashh20 күн бұрын
@@aymeric-devv You can just change the "Crouch = input.Crouch.WasPressedThisFrame() ? CrouchInput.Toggle : CrouchInput.None"
@redmario54663 ай бұрын
floppy hand
@cosmiccadet84722 ай бұрын
For anyone having the issue where the "PlayerInputActions" namespace doesn't exist... Remember to check the "Generate C# Class" box on the actual Input Actions asset you made at the beginning. :)
@piyushguptaji4023 ай бұрын
why tf can't youtube recommend me more of these long guides. I really love em ❤
@hiqqoqotamus3 ай бұрын
This movement with all the camera effects and tilting looks really nice. Good job. I'm gonna go make my own version now. :)
@InexplicableVibes3 ай бұрын
I watched this in one sitting while cooking and loved it. I would love to see more in this style on KZbin in general!
@juillotine3 ай бұрын
+1 I watched it in one sitting and I loved it too I especially liked the visualizations for the velocity and acceleration whenever he wrote a function to make it better. Super informative!
@AHWilliams614Ай бұрын
Sir you have gotta give a part two with the grappling, wall running, and so on. This was an outstanding video
@ChukilledАй бұрын
I didn't watch the entire tutorial But God damn that final product is slick
@RugbugRedfern3 ай бұрын
This is an amazing resource for developing a character controller! It's really cool to see such a detailed breakdown. I probably won't be able to watch it all in one sitting though 😅
@KeenanWoodall3 ай бұрын
Thanks!
@6Abdellah93 ай бұрын
I’m sitting here for the next 8 hrs
@vivek_sharma9773 ай бұрын
Glad to know I'm not only one whos attention span is cooked : )
@jarred77213 ай бұрын
Amazing video! Clean, concise, and outlines your thought processes and how you construct your code in a way that is easy to follow and makes sense. I would love to see more content like this.
@aymeric-devvАй бұрын
Its very difficult for me but its an encredible video ! thank you. 5 minutes of your video is one hour for my...
@RainDevs25 күн бұрын
This video was incredible. Loved every second of it! Took me about 4 hours to get it all working my own project. Only critique I might have is that sometimes your code shows up really fast then cuts away before I have time to pause it. One thing you could do is at a little stop sign icon to the top corner of the video to indicate a cut away is coming and I should pause. All in all super education and informative. I had a lot of fun implementing this!
@KeenanWoodall25 күн бұрын
@@RainDevs thanks for the feedback. All good points 🙏
@awewalk-ld7fzАй бұрын
I have followed the whole video and its working Now I am waiting for the next video for wall running and other mechanics(please upload it) Overall a very great video
@xecto1206Ай бұрын
Oh MY GAHHD! That magic ability at the and is jaw dropping! The cartoony vfx style and smoothness is rlly good. The only doubt i have while being halfway through this project is that its too complicated for me to understand the codes. When we want to add 1 simple thing we still put lots of efforts and knowledge into it, scared of the idea if i can or not move on after following the video and be able to implement my own stuff.
@TrentSterling3 ай бұрын
This is a very nice breakdown/tutorial. Much more in-depth than a brakeys or dani style FPS controller!
@RainDevs26 күн бұрын
This is by far the best tutorial I’ve found on this concept. Looking forward to seeing more from your channel.
@blinkachu5275Ай бұрын
Wow, finally someone that actually deep dives into this subject, thank you so much I've made many CharacterControllers myself as I really hate relying on storebought stuff, because if something goes wrong you don't know where, and most of the time you can't get the feel you're going for. I currently have one that works well but I always love learning more and having an hour of footage of a really well made character controller is just what I need, thanks ^-^
@bore_incАй бұрын
GOATED tutorial, definitely a must watch 🔥
@erikponti1753Ай бұрын
Love the video! Please expand on this controller with fps hands etc if you have the time. Really educational.
@azagalplay52493 ай бұрын
This is amazing, you uploaded that video just before I started working on my own character controller, so thank you, this will help me greatly as a base to my own movement
@minimastudios_3 ай бұрын
so good! Over the years never seen a good controller like this laid out, and with unity taking a poop and tutorials dying down i didnt know if we would ever see one, really cool stuff thanks!
@lordkelvin13 ай бұрын
Really great video! So juicy and satisfying already. Would love more of these :)
@NotElayn3 ай бұрын
Loved it. Watched it completely in one sitting. Amazing stuff
@KeenanWoodall3 ай бұрын
Yay! Thanks :)
@bimbom97122 ай бұрын
this is unbelievably helpful, thank you so much
@coldtech062 ай бұрын
Thank you for the video, i hope this inspires people to create more movement based games, i surely will be
@matej5383 ай бұрын
this is great. maybe you could cover other topics such as how you go about sound design.
@sorathedev67393 ай бұрын
I love the camera math part and the way u organize code Just a small suggest but u can bring b-hop or simply some source movement, kinda fun to play around
@AmbientMood3 ай бұрын
Great breakdown! Would love to see this expanded to include wall-running as you mentioned and possibly vaulting or climbing if you have a good approach for that.
@melipefello3 ай бұрын
Great video, problem-driven with very clear examples :)
@hanya-chan4543 ай бұрын
one of the best advanced tutos, i love the animation too for the explanation, keep the work
@jamesramsaran37493 ай бұрын
This was excellent. Hope you continue making dev logs like this. Subscribed.
@Superuru7892 ай бұрын
This is an amazing resource for a start for my project, are you planning on doing a part 2 video with your dash, wallclimb and grapple hook abilities ?
@kaiser91993 ай бұрын
this is crazy u deserve more views
@fkeyzuwu3 ай бұрын
one of the best character movement tutorials I've seen! all the little juice tips are really nice quality as well
@dude254211 күн бұрын
FOUND IT AGAIN!!!!! WAAA SO HAPPY
@bizzlewizzle13 ай бұрын
This was really helpful information. I learned a lot. Thank you
@hotfirefly3 ай бұрын
Give me Tribes Ascendant vibes good job
@Гремаз-с3й2 ай бұрын
Awesome video! Would be cool if u made tutorial on how to make grappling hook with your controller
@_KillerD_3 ай бұрын
Thank you for this video dude
@guille_dlcАй бұрын
This is great
@gasparrivoiregaiao13213 ай бұрын
Hey, I tried to make the controller on the version 2022.3 37f1 and when Ifollow everything, the character model is not moving and the inputs don't work either :( But the controller is soooo impressive, maybe it's just to hard to understand for me for now sadlyy
@dreamingkyleАй бұрын
man... i needed this...i wanted to learn and understand in depth of what you are doing... hahahah i understand a few but its like night and day difference to how advance your knowledge in physics programming in unity... where do I even start... I think I can just copy what you did and try to learn from there... copying can only go so far without understanding... where do you even get this knowledge hahahahahahah... nice vid!
@KeenanWoodallАй бұрын
@@dreamingkyle just keep doing what you’re doing and over time different bits and pieces will click. Your instinct to avoid copying is a good one. If the math in this vid is unfamiliar, start with something super simple and figure it out yourself, like a bouncing ball, pendulum or spring. I’m not even very good at math, but with an intuitive understanding of the basics you can go really far. Intuition is just something that comes with time and practice. Use KZbin as a way to get introduced to concepts but go off and program stuff without tutorials as soon as possible because that’s when the real learning happens. Stick to it and you’ll get way better than you thought possible.
@dreamingkyleАй бұрын
@@KeenanWoodall @KeenanWoodall thanks! im still way far off, i barely able to get the hang of Enums, UnityEvents and Interfaces. I think my next stop would be learning the concept of state machine - but im always having a trouble trying to architect or structure my code... from OOP to SOLID principles - applying it in a practical sense is the challenge. I'd like to ask if you know any particular resource that you can point to for the basic fundamentals - like you said figuring out the basic will go far. Honestly, I dont even understand what you were doing with the vector3.dots and was like wait you can do that? what does that even do? hahaha then the quaternions and lerps... anyway, I've just been scouting for resources 3d movement guide for a game in mind (pretty ambitious but i has no skill set, yet) . Its just that coming across your video made me curious then it slapped me hahahaha - i thought i could understand a bit but yeah just a bit but not much.... I do like the way you present it tho - you got pretty interesting stuff going on. love you took the consideration of making the game feel intuitive!
@王灏-x6g2 ай бұрын
Very nice character control!! in the end, i want to know how do you achieve the dynamic arm movement?😊
@KeenanWoodall2 ай бұрын
Thanks :) Each joint of the hand is animated with spring physics. This asset makes it pretty easy assetstore.unity.com/packages/tools/animation/dynamic-bone-16743
@王灏-x6g2 ай бұрын
@@KeenanWoodall Thanks for your answer and hope you make more interesting videos in the future😁
@6Abdellah92 ай бұрын
took abt 5 hrs to complete first time using unity 6 and haven't gotten into the flow yet with the inspector overall very nice but will hard to build onto as it uses the kinematic character controller as a base which I got no experience using
@KeenanWoodall2 ай бұрын
Just about every technique in the video can be applied to any kinematic character controller system/asset. At the end of the day all movement boils down to a single velocity vector which is a universal way to describe movement :)
@6Abdellah92 ай бұрын
Yh I got the hang of it after going through the walkthrough. it was the functions that where added by the controller that where confusing but the walkthrough made sense of all that. I managed to add rocket jumping and wallrunning even through the wallrunning doesn’t feel that good yet
@6Abdellah92 ай бұрын
The rocket jumping is super fin
@6Abdellah92 ай бұрын
Especially when sliding u just zoom all over the place
@xeni_games21 күн бұрын
Amazing!! I have one question. I tried to implement the same thing, but every time the character moves, the character itself is slightly choppy. This is similar to the phenomenon that can be cured by selecting Interpolate in Rigidbody. Do you know of any solutions?
@KeenanWoodall13 күн бұрын
Odd. The kinematic character system should have interpolation enabled by default but I'd check that first. docs.google.com/document/d/1qT71uGaUO4UmK1NbW9-UsrX1G-0dWWQ2JQlKWBH0dIw/edit?tab=t.0#heading=h.mcpy681l25ql
@mickeyouse68083 ай бұрын
This is a great video ! I would love to see more like that in the future ! 🔥🔥 Two questions : Do you think using a Rigid body for complex movement mechanics is a good idea ? Also, do you intend to create a Discord server ?
@KeenanWoodall3 ай бұрын
Rigidbody vs kinematic physics really depends on the type of game you want to make imo. If you want responsive/bespoke character controls, kinematic physics is the way to go. If you want your character to have complex interactions with the rest of the physics-world you probably want to use a rigidbody. I think rigidbodies work well for casual movement mechanics and can have fun possibilities for emergent gameplay, but for those same reasons they can be hard to wrangle when you want explicit control over movement/physics.
@RainDevs25 күн бұрын
Hey I'm attempting to implement the slide audio like in your showcase at the end. Where did you get your audio clip from? I've tried making my own and they all sound terrible LOL. Also did you implement the audio in the PlayerCharacter class or make another external one and pass values into that?
@KeenanWoodall25 күн бұрын
Yea the slide sound took a bit of trial and error. Iirc I ended up with a mix of tires on gravel and rustling tarp. I found those sfx on Soundly. It’s paid sub but it’s really good imo. For the audio code I have a separate class for player audio that has a tick function which is passed the current and last character state which it can use to drive the audio. I also added some event flags to the character state for extra events that external stuff like the audio system might need to know about
@KeenanWoodall25 күн бұрын
I used animation curves to drive the volume/pitch of the looping slide sound based on speed so it’s louder higher pitched as the player slides faster. The clip is always playing and fades in while the player is sliding
@RainDevs25 күн бұрын
@ awesome I’ll look into that website. That sounds like the solution I ended up with for audio. I created a player audio class and then passed the state variables to it from the player.
@RainDevs25 күн бұрын
@@KeenanWoodall ah smart. I was trying to start and stop it but it was very jarring
@todzifushigur02 ай бұрын
u r fk best man
@maxikittikat10 күн бұрын
Im i bit stuck and confused with the crouching. Because after i implemented the slide as well as the _state, _tempState and _lastState when standing still and not moving and not under an object when crouching and uncrouching it wont uncrouch unless i move or jump. Ive backed up my project each time and compared my old working version with my new version with the uncrouching broken. The weirdest part is even if i force the state, lastState and tempState to stand it still wont uncrouch without moving its like it refuses to run the section of the code that checks if you should uncrouch unless your moving. If you could somehow help me out id really appreciate it (nevermind actually just for anyone else with trying to add a sprint state or any other state in the stance enum if you are using an if else statement at the beginning of UpdateVelocity() do not put _state.Stance = _lastState.Stance in else but _state.Stance = _state.Stance)
@lethalbacon6080Ай бұрын
I am new to game dev so do not take my comment seriously :D. At roughly 9:58 you clamp the movement direction to a magnitude of 1. It would be better to just use Normalize since there is less computational over head and it is what normalize was intended for. I would change it because less computing on something as common as moving could be the optimization someone needs. Please let me know if this even makes a difference?
@lethalbacon6080Ай бұрын
Also why are we multiplying the magnitude of our _requestedMovement with our groundMovement at 12:04? If we clamp our magnitude or normalize it, we will be multiplying it by 1 always or by 0 when we are not moving. It just does not make sense unless there is some weird situation where it is needed...
@KeenanWoodallАй бұрын
Thanks for asking. Normalizing would be fine if you only need to support keyboard input, but by clamping you also support joysticks whose input along an axis can be
@lethalbacon6080Ай бұрын
@@KeenanWoodall awesome man, thanks! I knew there was some special case here.
@MoonMan-i9i3 ай бұрын
Please release the unity proj file for this controller this is so good 🙏
@Coffeemancer2 ай бұрын
you're making Tribes?
@erikponti1753Ай бұрын
Is there a way to add "bunny hopping" using this controller set up?
@KeenanWoodallАй бұрын
You could definitely add it, but sliding is the main mechanic that this video focuses on so bhopping is not covered.
@alexanderfloratos931210 күн бұрын
did you try to find a way? im trying to implement but i think we might have to adjust the code for the Kinematic Character Motor but im not 100% _requestedRotation = input.Rotation; // take 2d input vector and create 3d movement vector on the XZ plane. _requestedMovement = new Vector3(input.Move.x, 0f, input.Move.y); // clamp the length to 1 to prevent moving faster than diagonally WASD input _requestedMovement = Vector3.ClampMagnitude(_requestedMovement, 1f); //Orient the input so its relative to the direction the player is facing _requestedMovement = input.Rotation * _requestedMovement; this code above is still applicable and its basically the wishDir calculation. we have to take the scalar projection of the velocity onto the _requestedRotation in order to determine "currentSpeed". then idk what to do next or how to apply the vectors. in the bhop logic it says: addspeed = wishspeed - currentspeed; if (addspeed addspeed) { accelspeed = addspeed; } for (i=0 ; ips->velocity[i] += accelspeed*wishdir[i]; }
@bonse20002 ай бұрын
project source pls?
@skyy1906Ай бұрын
How did you do to use C# versions greater than 9.0 tho? Mine says it needs version 10.0 to write some parts of the code but I can't seem to make it work
@KeenanWoodallАй бұрын
I'm curious which parts of the code are causing trouble? I don't think I'm doing anything that would require C# 10, and if I was mine shouldn't compile either :P
@skyy190629 күн бұрын
@@KeenanWoodall this is the part of the code that is causing me problems, I didn't advance any further bc I couldn't get this resolved, so idk if there's any more than this. public void UpdateRotation(ref Quaternion currentRotation, float deltaTime) { var forward = Vector3.ProjectOnPlane { _requestedRotation * Vector3.forward, motor.CharacterUp }; currentRotation = Quaternion.LookRotation(forward, motor.CharacterUp); }
@KeenanWoodall29 күн бұрын
@@skyy1906That looks fine at a glance. What is the exact error message and line that causes it?
@skyy190628 күн бұрын
@@KeenanWoodall this is the error message "Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater.CS8773" Specifically this line " var forward = Vector3.ProjectOnPlane" I genuinely don't know what could it be, I already rechecked the code a bunch of times and nothing is wrong, it's weird
@KeenanWoodall28 күн бұрын
@@skyy1906 oh you have braces instead of parentheses for the ProjectOnPlane function call
@KAIZENTECHNOLOGIES3 ай бұрын
Great video keenan. In future tho, could you make these types of videos more beginner friendly. You're going way too fast 😅
@KeenanWoodall3 ай бұрын
Thanks for checking it out! Yea I agree this vid 100% too fast for beginners, and is more aimed at intermediate devs who I feel don't have as many resources :P That being said, I am thinking about how I'd like to tackle beginner-oriented content in the future. I just want to find a format that I feel puts comprehension first, and isn't simply an entertaining video under the guise of an educational one (this is a massive problem with edu-tainment imo)
@KeenanWoodall3 ай бұрын
I am self-taught, so I clearly have strong opinions about beginner education on yt 😅When I started out in high-school I spent *so* much time following tutorials, but as soon as I tried to make something myself I was lost! so I admit the pace is fast to _discourage_ copy/pasting and _encourage_ simply watching and learning - with the hope that viewers can apply concepts to _their own_ games instead of creating a carbon copy. Showing the entire process line-by-line removes any mystery which I like, but it invites beginners to copy/paste without actually understanding what they're doing - not saying that's you ofc, just thinking out loud :)
@KAIZENTECHNOLOGIES3 ай бұрын
@@KeenanWoodall yeah from the first five minutes alone, a beginner would probably spend half a day trying to figure things 😂 I instantly gathered that it is an intermediate video from that part because I had to do some research to really learn what your intentions behind each change
@KAIZENTECHNOLOGIES3 ай бұрын
@@KeenanWoodall luckily for me, I know how to code at an intermediate level in other languages, so I know not just copy and paste 😅 (which I've done a lot in the past). Good job on the videos bro, keep it up!
@mehmeh88832 ай бұрын
Chapters please:3
@KeenanWoodall2 ай бұрын
Added!
@mehmeh88832 ай бұрын
@@KeenanWoodall ty!
@azagalplay52493 ай бұрын
I can't seem for the life of me, fix the gimbal lock problem that occurs when trying to do a flip, I tried using Quaternion.lookrotation, Quaternion.AngleAxis and some more, I couldn't make it work, how did you fix that issue ?
@KeenanWoodall3 ай бұрын
I don't think I have. My understanding is that It's an unavoidable property of 2-axis rotation. Unless you allow the camera to roll on the z-axis like in a 6DOF game and use quaternions you'll always have gimbal lock when looking straight up/down and then trying to look along a different pitch/yaw.
@azagalplay52493 ай бұрын
@@KeenanWoodall I see, thank you for the response anyway !
@azagalplay52493 ай бұрын
@@KeenanWoodall I found the bug, so it seems the problem didn't come from the usage of euler angles, but from how the player follows the camera's rotation. Since the player character rotates using the camera's forward direction projected onto its up vector, when doing a flip, the rotation also needs to do an instant flip. The problem with this is that since the camera is parented to the character, the camera will also instantly do a rotation with the character, and both will go crazy in a feedback loop. The solution was to deparent the camera from the character so that the camera isn't affected by the player character's rotation.
@azagalplay52493 ай бұрын
By the way, thanks a ton for that video, it worked wonders as a base for the other movement techs, I already worked out a ground slam that's a mix between yours and ultrakill's, a dash and the multijump. I'm currently trying to do wallride, though it's currently pretty hard to find an implementation that doesn't stick me like glue to every wall that's too close to me and destroys my momentum. Wall to wall transition is also something I'm struggling with.
@KeenanWoodall3 ай бұрын
@@azagalplay5249 Yes the camera should be unparented from the character. The hierarchy was created as follows at 2:25: Player: Player.cs (doesn't move/rotate) Character: PlayerCharacter.cs Camera: PlayerCamera.cs Sorry I did that part a bit fast so it might not have been clear
@nicklesnn3 ай бұрын
shmove
@vivek_sharma9773 ай бұрын
I use the same vscode theme so now i have to watch the entire thing its like watching myself code, just that im not as good as you 🥹