Attention | Topic was automatically imported from the old Question2Answer platform. | |
Asked By | BrightC | |
Old Version | Published before Godot 3 was released. |
Hello everyone,
I started using Godot recently and am currently trying to get a simple platformer to work. I followed the tutorial on 2DKinematicBodys (http://docs.godotengine.org/en/latest/tutorials/2d/kinematic_character_2d.html ) and so far everything is well and good. However, upon trying to create my own platformer based on that tutorial, I ran into a number of issues.
First of all: Downwards slope movement. While using the collision normal vector - like the tutorial suggests - works fine for upwards slopes, I can not use this technique for downward slopes. This means everytime my character moves on a downwards slope and is in the air for a very brief moment due to the gravity not being strong enough to pull him back on the ground immediately, it will look like he’s “hopping” down the slope, which is terribly awkward.
I’ve tried a variety of things in order to prevent this from happening. At the end of each _fixed_process I would check if test_move(0, 16) (16 being the maximum amount of pixels that the character could step down without jumping) returned true. If it did, I would move(0, 16), which should make the character move back onto the ground. While this did work, it also made the movement extremely jittery, for reasons unknown to me. As if everytime the character moved, the following frame the character moved a few pixels upwards before making its next move.
For my next attempt I increased the gravity to levels where it would drag my character immediately back onto the ground, unless the slope was very steep. Again, while it worked, it caused the same jittery movement I had before, ontop of having the annoying side effect of accelerating the downwards movement speed to unpleasantly high levels (Which is another thing I don’t fully understand, since any gravity that is being applied should only be able to drag the character down vertically, with the horizontal movement being unaffected).
Which leads me to my second problem. While of course it seems realistic for characters to move quicker when moving down a slope and slower when moving up, it is undesireable in my case. I understand this behaviour must be linked to the Vector2.slide function the tutorial is using, but I am not sure how to avoid it, especially since I don’t fully understand the slide function, and the documentation on this engine in general seems to be somewhat sparse. (I don’t quite understand why it takes a Vector2 as parameter. Does it simply take the length of that vector and converts it to a different angle? Also, why does the character not run up walls with the code from the tutorial? If it runs into a wall, the collision normal vector would be pointing to the left/right, which means sliding alongside that would result in moving up.)
When I was using Godot for the past few days I was quite happy with it, seeing how it strikes a nice balance between complexity and efficiency, after using a large number of other game engines. However, the issues listed above turned out to be rather frustrating. If anyone has any solutions or suggestions to either of the problems (or even an entirely different approach from the tutorial), they would be very much appreciated, since I would really like to keep using this engine. Thanks in advance!
the link is broken
tiernich | 2016-04-17 17:45
Thank you for the hint, the parantheses broke it. It’s fixed now.
BrightC | 2016-04-17 18:16
since any gravity that is being applied should only be able to drag the character down vertically, with the horizontal movement being unaffected.
You can help the character to stay on the downward slope by adding an Area2D and inserting a force field against the slope perpendicular to it. This way you don’t need to play with the gravity and it could help the character to not jitter.
Just one idea.
genete | 2016-04-18 12:02
I am pretty much on the same boat as you, friend.
I actually went towards a different approach, using this whole series of videos as a base for my own controller. The guy uses unity, and I am kinda like “porting” it to godot. I am a fairly new programmer myself and I believe it is just because I haven’t the skill to code that I wasn’t able to progress as fast as I would like.
Nevertheless, it is a really good approach to platforming with slopes. Have a look.
I wanna follow your and this Question developtment to see what more seasoned programmers can do.
brunosxs | 2016-04-18 12:29
Thank you for your suggestions so far. I did some tests on the KinematicBody and might’ve found where some of the problems originate from. While a KinematicBody doesn’t move on its own, the movement is still not perfectly precise when you move it. That means, contrary to what my intuition was, the move method will not be pixel-perfect and may in fact cause the KinematicBody to move horizontally even though the move vector points straight down. That is what was happening when I applied the gravity on a slope. I am quite certain that the very same behaviour causes the jittery movement, simply because the KinematicBody will end up one or two pixels away from its destination. While I guess this is acceptable for most games, in this particular scenario even the movement of a KinematicBody is too unprecise. The same limitations apply to the test_move command, making it equally useless to check for collisions here. However, I might have found a way to implement objects with pixel-perfect movement. Every Node2D comes with a set-local-x/set-local-y/set-pos method, which can be used to move it around. The collision checking is a lot more tricky and I am still trying to get it to work myself. Obviously you can access the world in your game and its so called “direct_space_set” ( World2D — Godot Engine (latest) documentation in English ), which, from my understanding, seems to be the object managing your world’s collisions (and physics in general). It provides the function intersect_shape amongst others, which you can use to check which shapes are colliding with the shape you passed to the function (for instance the collisionbox of your character). If the number of returned shapes is larger or equal to 1 and that 1 shape is not the character itself, it means there is a collision at that position. The problem I ran into now is that for some reason calling get_world_2d().get_direct_space_state().intersect_shape(get_node("CollisionShape2D").get_shape())
will crash the engine. (The console will literally just print “shit?: No error” ) My friend and me are currently trying to figure if this is a bug in the engine or if we’re just using that function wrongly. If anyone knows anything on that matter I would really appreciate the help.
As for the Unity tutorial: I don’t have time to look into it in-depth right now, but to me it seems it makes excessive use of raycasts, which I personally consider a huge mistake ( although even the Godot documentation encourages using them, annoyingly). While they’re useful in some situations, they will reduce the collision box to one or two rays, between those two rays, ANYTHING can happen, and in my experience it is very rarely the case that this little data is enough to react to any reaction accordingly.
EDIT: I managed to make it not crash, I’ll post the whole solution once I’m completely done with everything. If it works, that is.
BrightC | 2016-04-18 14:47