godot
godot copied to clipboard
Improve Godot character controller template
Superseed #66723 (as I added the comment changes)
This PR aims to improve the default template of the Character Controller by making it ready for use.
When I added the first template for the character body, the goal was to show how to use move_and_slide
correctly, in a simple way, since it was often a source of issues.
The script contains some problems:
- as @cbscribe noticed, using speed as friction means stopping the body immediately
- the friction was not frame independent
Moreover, the script was too simple, It was not good enough to be used as it is. For example, I saw a video tutorial that explained how to make a character controller starting from the characterController template, this is what makes the template less interesting.
This version aims to have the best possible character controller while remaining simple and short.
New features:
- support acceleration
- "run/walk" support (to be discussed)
- friction value different from the speed and independent of the frame.
- [2D only] additional friction when changing direction (I find that it makes sense in 2d but it can be deleted if you find that these two lines are too much)
- [3D only] addition of a camera with a spring arm & mouse movement with camera out of the box
Next steps:
- [ ] waiting for feedback on the new changes
- [ ] apply the changes to c#
Showcase:
Add a ground, a CharacterBody and attach the template:
https://user-images.githubusercontent.com/6397893/221202291-942ed13c-2445-414a-98b5-8bc75389e09b.mp4
@cbscribe & @aaronfranke you could be interested as you worked on the previous one.
Bugsquad edit:
- Fixes #74216
- "run/walk" support (to be discussed)
I think this makes sense to add, as this lets you test reduced walking speeds without having a controller (or tapping keyboard keys repeatedly). This has an impact when testing AnimationTree blending, for instance.
I'm of mixed minds about the addition of the camera in 3D. For a lot of users, this is going to be the default script that they use for a character body. I feel like it should be as generic as possible, in order to allow for modification to suit different needs.
On the plus side, it does reduce the number of steps needed to get a working 3d character up and running.
Once we've locked in the code changes, let's make sure to take one last look at the comments to make sure they're clear and match the code.
Thank you for your feedback. I see that the point of discussion is the camera.
I think the best approach would be to have a scene as a template, unfortunately this is beyond the scope of the PR, but I think is the way to go ans should be implemented in the future.
So the options for now:
-
(the one I used): all in one script, it makes the script a bit longer but it has several advantages:
- beginners friendly
- fast prototyping, in one click you have a complete character controller
-
keep it minimal: as the template aims RPS/FPS, I think the camera is essential, without, the user will have to code it himself, which makes the template less effective as it will have to learn how to set up the camera and apply the movement.
-
divide the template into several smaller ones. It's the most flexible approach for advanced users, we can have several cameras (FPS, TPS, RTS). But for a beginner:
- he might not know that there are other templates to complete the main one
- he might not know how to set up the camera in terms of nodes, he might miss the spring arm
I think that the first one has more advantage while waiting for a stage system. But as always, opinions are good to make a decision.
updated according to comments
I never figured out how to use spring arm correctly, so I'd prefer if the template contained it.
@cbscribe Do you have any suggestions for comments?
Doesn't applying gravity only when airborne break the property floor_stop_on_slope since gravity wouldn't apply any downward velocity while on a sloped floor? I think not applying gravity while grounded only sidesteps a greater issue with move_and_slide, #85971.
~~I see the proposition is replacing the lerp()
with a stable linear move_toward()
~~. For the record, if you want to preserve the smoother damping effect you may want to simply use the exponential form. It might make sense to demonstrate the use of both functions.
Here is a=lerp(a,b,delta*rate)
and why it's problematic at different frame rates (constant or not):
And here is a=lerp(a,b,1-exp(-delta*r))
which provides a stable behavior:
That's typically aligned with @expikr proposition in https://github.com/godotengine/godot/pull/81642
Edit: I just realized the original template doesn't use lerp
, it's only every tutorial ever built on top of it that seems to be doing it. It might still make sense for Godot to show how to properly interpolate.