I didn’t think to mention it before, but you can use script properties to expose those variables to the editor if that makes it easier for you.
It would! How do I tap into that magic?
Check documentation for go.property() and the script properties manual: https://www.defold.com/manuals/script-properties/
Raycasts now work great to determine which direction the player is colliding with.
However, the bug @ross.grams details above, is a showstopper to me. Is there a way of adding issues in Github that are not relating to editor 2?
Which issue is that? Describe it and I’ll create a ticket in out issue tracker.
Thanks! Nabbed the image from the post above:
Dynamic collision objects can get stuck between tiles of a Tilemap collision object.
This is probably (I’m guessing here) because each tile is converted to one Box2D fixture behind the scenes, rather than one larger fixture describing a block of tiles:
I just read up on composite collider, and yeah, seems exactly what I’m after. Although the composite collider is synchronous and seems a big feature in its own right. I’m simply after a fix for the bug where dynamic objects get stuck and incorrect collision responses are fired.
Are you having problems with dynamic objects or kinematic objects?
One big reason why the tile collision works the way it does, is that it’s dynamic in its nature. You can at any time change a tile, and therefore its physics.
Oh blimey, that’s good to know too! I can consistently replicate the issue with both kinematic and dynamic bodies.
In my case dynamic bodies are more important, because I want to save time by not coding the collision responses myself.
Just to be clear, this is not a “bug”! Box2D is working exactly the way it should be.
Because Defold treats each tile as a separate shape (for good reasons), life is a bit more difficult than you might expect, but it’s not all Defold’s fault either. Nor is this just a problem with tilemaps. Any time you want to build a continuous surface out of multiple pieces you’ll run into this. Unfortunately, no physics engine can read your mind.
Given two overlapping bodies, the physics engine will calculate the shortest distance and direction necessary to move those bodies so they won’t overlap anymore. It doesn’t really ‘prevent’ overlaps, it just moves them apart before things are rendered. With two rectangles, the normal of the contact will be vertical or horizontal depending on the amount of overlap in each direction.
In most cases, gravity is going to cause a vertical overlap every frame that something is ‘resting’ on the ground. As your body moves across a seam in the ground, this vertical overlap will be larger than the horizontal overlap from the seam for possibly a frame or two, giving you a horizontal contact normal.
The deeper the vertical overlap (because of low framerate or something), the worse it is.
Of course it happens with regular objects too (no tilemap)
For most games it’s not really possible to simply avoid this issue by making every floor a single continuous shape. It’s pretty much guaranteed in any infinite runner or any other platformer where the levels are made in separate pieces. And for example what if you want a one-way platform sticking off the end of a solid platform? Those two bodies must have different properties, there’s no way for them to be a single shape.
Any robust platformer (with any engine) is going to have to deal with this issue. A specialized ‘physics engine’ like Bump might help—meaning that someone else solved the problem for you.
I think you will find that using a dynamic body for your player will be much more work in the long run, especially considering the limited subset of Box2D’s features that Defold gives you access to. With a dynamic body you will have to deal with forces and friction, you can’t just move the player where you want, you can’t change collision groups at runtime so I’m not sure how you would do one-way platforms, etc. Kinematic bodies let you skip all that stuff. You can control them just like any other game object, but they give you detailed collision information (which you can use or ignore as you like).
@ross.grams: That is an amazing writeup and summary of platformer physics! Thank you for taking the time to put this together!
As a side-note: I’ve had a module for simplifying platformer logic lying around in my toolbelt lib for quite some time. I’ve been meaning to move it to a separate repo and share it as a Defold library project. Maybe it could be useful for someone who quickly wants to get the physics for a platformer game up and running: https://github.com/britzl/platypus
Thanks for this amazing info. I never really considered it a bug Because I knew it was something to do with the tiles acting as seperate static objects. I was more looking for some sort of workaround. But It could be fixed by the Defold team if they ever decide to rewrite how tilemaps are converted to box2d static objects such as treating adjacent tiles as a single object at run time.
I was using libGDX before and a programmer that I follow on youtube (Dermetfan) created a Box2d assist library that did just that. It converted tilemaps (That were made in Tiled) to Triangulate d box2d objects. But I never got around to using it outside of the tutorial because I was avoiding Box2d at the time.
Kudos for a fantastic writeup @ross.grams, beautifully explained. I always did consider it a bug, because I thought it strange that a dynamic object can get stuck between two static fixtures even though there is (literally) no gap between them. Bug or not, would be good to figure out a nice fix to make it work better in a platform game.
@britzl, I had a quick look at your solution. It seems to fire only four ray casts, which means there is still no way of knowing when the player leaves a platform? I would have thought you need eight rays to accurately determine this. But would be very happy to be wrong in this case!
You could have a trigger shape at the feet of the character to determine if the player is standing on a platform or not.
The problem I have is that the dynamic body sometimes gets stuck between tiles. I managed to figure out all collisions with ray casts. It works really well, so if I was able to solve the getting stuck problem the prototype would be finished.
I could use a kinematic object instead and try to hack a way to avoid the collision responses that causes the issue. I’d rather not, though, because in my game I am actively using friction, forces and all the other stuff Box2D does so well.
As a side note, I noticed that triggers appear to lag a bit behind the main game object for some reason. See this thread: Determining all collision directions for player
I use a combination of physics shapes and ray casts. Physics shapes for resolving/separating kinematic collisions. The ray cast is used for detection of “state”, ie wall and or ground contact. Now that I think of it I probably need two downward facing rays to detect when standing really at the edge of a ledge.
Yeah, that’s what I meant. I think a generic solution could be eight ray casts, like the illustration with Link above.
I’ve updated Platypus to use two ray casts down to detect the edge of ledges. It works a lot better. I’ll continue working on the lib and add examples of directional platforms, climbing ladders and so on.