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); }
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...
@@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;
+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!
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. :)
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 😅
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.
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!
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 ^-^
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.
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
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
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!
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.
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 ?
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
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
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 ?
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.
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
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!
@@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 RU-vid 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.
@@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!
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?
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...
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
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
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 :)
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
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
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
@@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); }
@@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
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)
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 :)
@@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
@@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!
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 ?
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.
@@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.
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.
@@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