#shorts #gamedev One-way platforms are very common in platformer games, so in this video I go through how I implemented them in my game. This game is made with LOVE, feel free to check out my full tutorial: • [2021 Update!] Make Ga...
I think this solution is better. Instead of constant, repeated checks on every platform you only do a check when you need to. Event driven logic is much more performant.
You can avoid all the constant checks by checking the collision normal when colliding. The normal will tell you which direction your hitting the platform from. Can just ignore if hitting from bottom 🤟
No, that would be slower. Not that it matters, either way will be plenty fast enough, but installing a collision handler that runs for every collision event and check whether it's a player x platform collision is almost certainly more work (and importantly, less consistent/predictable amount of work per frame) than just iterating all the platforms every tick. That said, you probably want the collision handler anyway be able to conditionally ignore specific collisions instead of disabling the collider entirely.
@@notnullnotvoidIs this a joke? No way a collision handler (that Already has to run mind you, you're just hooking onto it.) is slower than running a check for every platform every tick, even with optimisation for only doing the closest few.
@@nintySW Yes way, it sure is slower. An extra (more complex) check on *every* ongoing collision every frame, vs. a simpler check per platform per frame and then the disabled hitboxes presumably don't even even enter broadphase at all let alone enter narrow phase and have their contact patch calculated? None of this matters, mind you, but yes, the contact listener approach will be slower. You learn these kinds of things in the process of shipping a physics-based game with a perf-sensitive sim step.
Nice video! Unsolicited fun fact to boost the _algorithm_: In the original Super Mario Bros, the game checks if Mario is landing on an enemy (good) or being landed on (bad) just by checking Mario's vertical velocity component. Thus, you can squash a goomba from below if it lands on Mario while he is falling slower than it.
Does that make sense? If a Goomba is walking then Mario's velocity is certainly greater when he lands on it. Wouldn't the Goomba need to be falling slower than Mario in order to squish it from below? Which should also be an impossible situation because if the Goomba is above and falling slower than Mario, Mario should never be able to collide with the Goomba.
If your saying to add a single square that only has a collision one one side, that works but it's a bad idea because the second the middle of your character goes threw it, it will teleport you forward till your fully out of it, or fully on the other side, I used to use this to make 1 way passages and stuff in my games but I stopped using this method
Games and even programs in general use an insane amount of checks per minute, I don't have much coding experience but I don't see why it's an issue to have more checks. From what I understand having checks is good but let me know if that's not the case
@@DARK_AMBIGUOUSjust make the one sided collision only apply to a specific collision box and have an additional thin collision box at your feet for ground detection
@@user-mf4uo9ox2y More checks gives performance losses. A few platforms on their own wouldn't do much to the optimization, but it would add up with other things being coded in similar ways.
What I did on my one-way platforms was make two hitboxes: one for the bottom and one for the top (in the case of your grated platform, it would be the 2 highest pixels). The bottom hitbox lets anything pass through it, and is just there as a sensor: the higher hitbox would have no collision with anything touching the lower one, but would with anything not touching it.
pretty clean implementation, actually, very few checks needed. and dropthrough could be implemented by just shifting the player's collision box down by 3 pixels when pressing down on a platform, easily hidden with a brief and simple dropping animation
@@theonewholearns2711 nah you'd extend the lower hitbox out a bit at the sides to avoid that unless you want to have ledge hanging on them, in which case you'd have another hitbox at the edges and a ledge grabbing hitbox the top half of your character to acrivate the ledge hang state.
In Unity you can add a platform effector 2d and it makes it a one way platform automatically, just make sure to check "used by effector" on the collider you are wanting to change.
@@scrunky8683 dude it's one checkbox. I don't make tutorials but there's about a dozen on youtube I can think of. It's also in the documentation. Or you just look at some of the sample projects with platforms. You really just need to spend 5 minutes looking for it.
This works fine if it’s just a single player and simple npcs. However this falls apart if you have add multiplayer or any traversal ai behavior. Also the colliders will spend every frame checking the player’s y position. I’d probably tie the collider flag (i.e. the character’s collision layer) to the entity that is jumping based on it’s movement vector. If a player or entity is moving in the positive y direction, it should not collide with platform. On the way down if it moves in the negative y or is at 0 delta it should check if its collider overlaps the platform. If not then switch the collision flag back. The neat thing with this is you can also make the player “hop down” from the platform by toggling the collider flag based on user input.
Unity has a component called Platform Effector2d that you can attach to your colliders. It ignores collisions from specific directions if you enable the one-way option.
It's a completely negligible cost. Anything on screen is already doing a ton of processing just to render, checking a single variable and adjusting its collision state will barely make a difference.
@@GrandHighGamer those stack up tho. its def not a good practice. Plus, using observer-pattern checks - then verifying the collision's normal - for the matter is also much cleaner 99% of the time.
@@atiedebee1020 collision events... you obviously wont check it at every frame, just during collisions. you cant even check collision normals outside collisions
The velocity check or using the normal is probably the most efficient solution here, but another thing you could do is have another bigger collision box around the platform that checks if the bird is above or below it. So it only checks if the bird is near it, instead of all of the time
Wouldn't it be better to make the player two collision boxes split in the middle. So if players top half hits the platform first he passes through, and if bottom half it's solid. This would also allow for emergent gameplay and exploits by more advanced players.
Throwing more hitboxes at it is probably more computationally heavy. (I am assuming engine implementation details here, but it is reasonable in this case) which do you think would cost more? More collision checks, or a Y position check?
@@HashCollision just a standard collision_normal.y check for the default bounding box of the platform (no actual need to have more than 1); if collision_normal.y < 0, collide, else dont. infinitely less costly than checking (amt of platforms) * FPS * (amt of actors) all the time.
The way I had learnt to solve this is to create a variable to check if you're colliding with the platform or not and if you are, check the y-position until you're above the platform to allow you to pass through or to stop you. I also used this to allow the player to fall through the platform if they're holding down on it. This was technically intended for allowing sloped platforms but I never used any because I preferred blocky level design.
I didn't something similar in 3D for a end of studies project. Rather than check constantly, which doesn't work at scale, I only checked on collision, and then changed the behavior right away. Because I was on Unity and due to how their collision system is built, I just kept it "on" at all times and disabled it if the collision met my criteria (the call was the first step in handling the collision, and changing it to a trigger simply changed the behavior later in the call chain). I could then just enable it back when the character exited the box. One benefit of this approach was that it was not expensive and was still consistent. One drawback is that it was dependent on engine behavior, we couldn't know if another version of unity could break it. But in the context of our project, we could take the risk, as upgrading our unity version wasn't a current or future requirement.
It's more resource efficient to shift the logic from the static platforms to the moving entities passing torugh. Implement a collision check and snap entities above the tile if they try to pass trough them from above. It also enables more than just one entity to do the same simultaneously as the platforms keep their collision state the same at all times.
Located a bug: if you have an enemy that can jump, they will bonk against any platform lower than the player’s height. Jumping enemies cannot reach the player from below if they are standing on a one way platform
I think I can think of another problem with this method specifically: what if the one-way platform is tilted in some way? Where on the platform does it compare the player's height to?
I think it would be better if each entity's script checked if it should collide with platform depending on the Y position, So that the platform collider is always active but player and enemies ignore it if their position is lower. This way both player and enemies could move through the platform and collide with it from above at any time
Should make it more dynamic and any sprite that is below it ignores the collision, rather than changing the platform can't the interaction between the spirits and the platform
@@hiiambarney4489good use case for fixedupdate to catch it before the next frame. Race conditions are fixed by correctly ordering physics checks. In good patrern uodate should never check or update physics it is on a different framerule entirely so this couldnt happen. 😊
This might be a dumb question, but isn't this potentially a major performance issue? Since every collision is checking the player position at all times?
I made a type of terrain It is intangible if your movement is upward or if you are inside it, if you stay at the same height or if you move down, the platform is solid. Additionally I made it so that if I pressed jump while crouching my character would check the pixel right below him, if it was this terrain then I would move my character down one pixel, this way I could also go down the platform whenever I wanted. Although in my project it was my character who did the terrain checks, not the terrain.
2 things: One - I really like how you explain how it works (fundamenrally atleast) instead of just giving tutorials with pre-made assets, learning how to demystify black box game logic is a huge part of advanced game dev and I love it Two - as far as your solution goes, I won't say its performance problematic unlike other people, I think it's just fine for the scope of the project. But I would like to suggest that a more individual approach that focuses on general game objects instead of just the player would boost level and enemy design ability since it would allow enemy AI to take advantage of the game mechanic which is kinda hard but super worth it
Each object checking your height means a lot of computing. You could have the player check when it's colliding with the platform wether it's above or not. You would only need to check for one node (player) only once, at collide event
could just make a custom collider script for those platforms that adds a check on collision enter to see whether it was the player that collided and, if so, whether they are above or below the platform. Cuts down heavily on checks per minute and should still provide exactly the same functionality.
This'll definitely help. Making a metroidvania, and if you want to know how many of these are in one, play through one and take a drink for every new one you see.
I made different collision layers, one collier on the head that doesn’t collide with one-way platforms while body and feet do. when head overlaps with one-way platforms it changes the body and feet colliders to a “head” temporarily and when they exit it (either from jumping over it or falling below it they change back. This leaves less processing power (I think, since it only has to check colliders which it does anyway and not constantly check the Y axis of the player for each platform) and you can add this to enemies so they can jump through too! For this the platform needs to be thinner though, otherwise falling through the edges gets a bit wonky Another thing is that landing on a platform with your mid-body makes it shake but that’s fixable with side of body colliders that stops positive or negative horizontal movement and in this case because it’s a one-way disables it like the head All in all, instead of checking constantly it only checks when it collies followed by a bunch of if statements to determine what to do Again, I don’t know if this is better for the cpu but I believe so
For new Devs, it's best practices to eliminate unnecessary checks especially every frame all the time. In this case, U can use a proximity hitbox to trigger the check. Or Trigger check on every frame for X time when player jumps. Or when not grounded. Or the moment Y changes.
eyy this is a case where it makes sense to have the origin of the player at the bottom of their feet, but you of course can also do it with an empty, if say you wanted the player sprite to rotate from the middle and not from the bottom
If you have a lot of these checking every one constantly could be bad for frames and unoptimised. You could add an area where these get checked, so its not slowing performance
I have another solution that doesn't involve platforms checking on every frame Instead of using a box shaped collider, use a plane or a quad as a collider. Planes and Quads by default are one sided objects, being the front face the one with the collision, so if the player goes through it from below, it would ignore it until the player stands on top
This could become quite expensive. The best ways to do this is to disable player collisions when jump is active OR check if the player's directional heading is up, if so we disable the collision also.
See, when I tried this way back when for a high school class, I tried solving it by using the motion that you can have upward movement through it, but not downward. The flaw with that design choice is that a player or entity can be partway through a platform like this, which can result in clip-based glitches. By having the platform be in a different state depending on position of the entity it effects, this problem is entirely avoided. This is a really helpful solution to view the problem with!
I remember going from Super Mario Bros. to SMB2 and this was a big effing deal! Also, top down games having 8 directions instead of just 4. Kids these days will never know how mind-blowing these minor technological improvements were.
this probably depends on how much control you have over your platformer physics, but I'd probably just remove the side wall collisions entirely just in case
Now i'm imagining a system where just the player shoots out a little "jump bullet" whenever you press the jump button, which tries to collide with an object and, if it does, reads information about the object's position and context, and then tells the player how to jump
Holy crap man thanks. I'm working on a platformer right now and was stuck on just that issue. I thought I could just go around platforms, but the level design is making that difficult. Thanks again.
If this is what you got stuck on, and you saw this solution and thought "Wow that's a good solution", you shouldn't be making games. Go learn some basic math and programming instead. And I do mean BASIC.
@@spell105 person who thinks all true game devs are born with a gene that lets them detect poor coding practice intuitively, without gaining experience first, like some kinda gaming spider sense sorry op you werent born with the power of game dev etched into your soul, better give up on your dreams!
@@spell105I’d argue that trying to make a game is a good way to learn those things. People don’t have to be masters at their craft before they’re allowed to try to make something cool, and it often helps when figuring out what skills have been mastered and what needs to be improved. Op is doing just fine.
Yep, every platform has a Y property that represents its upper left corner's Y position, and then it compares that to the birds very bottom point (center + height/2)
Well if there ever is an enemy capable of jumping to chase you more effectively it could also fall through a platform intentionally (maybe only after the player touches the ground) as a way to keep chasing or to kill/get rid of the enemy if something related is below
If you're watching the video and stuck on how to implement it: Set the collision to disable when the *bottom* of the player's hitbox Y-level is below the *top* of platform's hitbox Y-level
In unity you can just use a platform effector and configure it to work this way, it can even include a falling effect where the player can go through the platform downwards jumping and pressing down button
For anyone using Unity concerned about efficiency, this is a perfectly valid solution, and is more efficient than using a PlatformEffector (unless you want some of the extra bells and whistles PlatformEffector provides). If you want, you could also split the collider in 2, and have one be a trigger that disables the other one, which is about on par with this CPU usage wise. Most of the complaints about efficiency assume your engine lets you intercept the collision and choose to ignore it before the effects are applied, which Unity doesn't seem to allow, at least in what I've found.
in my most recent WIP game, i wanted to make oneways in different directions, so instead of making four objects (onewayUp, onewayDown, etc), i just made one that does trig to check the players distance in relation to its angle and face. sounds complicated, but it was simple enough, and had the added benefit of working in ALL 360 degrees
Back in dev school I was doing a 2d game in ue4. The solution I found was to check if the character vertical velocity was positive. If it was then it would ignore collision, but if was negative or equal to 0 then it would block collisions. Jenky but it worked :D