Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.x] Fixing 2D moving platform logic #50166

Merged
merged 1 commit into from
Jul 15, 2021

Conversation

fabriceci
Copy link
Contributor

@fabriceci fabriceci commented Jul 4, 2021

The current logic to apply the platform velocity is incorrect. The velocity of the platform is added to the body velocity. However mixing those velocity cause issues, we need to apply the movement in two steps, first the platform movement, and then the body movement.

Plus, currently the movement was only added when the body was on the platform floor, we also need to apply it when we are on_wall

A big thanks to @pouleyKetchoupp for the help.

Fixes:

Note: as the changes will be a bit different on 4.0 due to latest API changes (and to avoid here breaking changes), I start with the stable branch, but the PR on master will follow.

@fabriceci fabriceci requested review from a team as code owners July 4, 2021 18:33
@pouleyKetchoupp pouleyKetchoupp added this to the 3.4 milestone Jul 4, 2021
@fabriceci fabriceci changed the title [3.x] Fixing 2D moving platform logic in move_and_slide [3.x] Fixing 2D moving platform logic Jul 4, 2021
@fabriceci fabriceci force-pushed the fix-2d-moving-platform branch 3 times, most recently from 227fceb to 4ed8d6f Compare July 5, 2021 20:01
Copy link
Contributor

@pouleyKetchoupp pouleyKetchoupp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea generally works well and the code looks fine except for a few details I've commented on.

It will need a master version to be merged so we can keep things in sync as much as possible between master and 3.x, and as a note, we'll need to fix this issue in 3D as well (but that's not a blocker to me).

I have a few comments on specific issues too:

#47366
Both kinematic bodies seems to be still stuck when the platform is moving down. Do you know what could be going on?

#27537
I can confirm it is fixed by this PR.
Project converted to gdscript:
Platform.Game.zip

#50155
The character not falling is fixed, but it looks like there's some lag in the horizontal movement now when the platform is going left, I'm not sure why:
move_platform_vertical_wall

I can confirm other mentioned issues are completely fixed.

scene/2d/physics_body_2d.cpp Outdated Show resolved Hide resolved
scene/2d/physics_body_2d.cpp Outdated Show resolved Hide resolved
scene/2d/physics_body_2d.cpp Outdated Show resolved Hide resolved
scene/2d/physics_body_2d.cpp Outdated Show resolved Hide resolved
@fabriceci
Copy link
Contributor Author

fabriceci commented Jul 6, 2021

Thanks for the review.

It will need a master version to be merged so we can keep things in sync as much as possible between master and 3.x, and as a note, we'll need to fix this issue in 3D as well (but that's not a blocker to me).

Yes I will add the 4.0 pr soon.

#47366
Both kinematic bodies seems to be still stuck when the platform is moving down. Do you know what could be going on?

Yes I saw it, the issue I tried to describe with the moving tilemap is fixed. However there is another one, the raycast not detect the collision when the platform move quickly which lead to stop the bodies. I will open a new issue for this one (or change the title/description if you prefer).

#50155
The character not falling is fixed, but it looks like there's some lag in the horizontal movement now when the platform is going left, I'm not sure why:

I thought it was expected : when the platform change direction on the left, during few frames, the body no more touch the platform, so it will stop following it (plus it takes the inertia by leaving the wall). You can get rid of that by increasing the speed or snapping when slide into the wall.

But I was wrong, when I increased the speed, it seems there is one frame delay even with sync to physics.

@fabriceci fabriceci force-pushed the fix-2d-moving-platform branch 2 times, most recently from d41069d to 582962a Compare July 6, 2021 13:51
@fabriceci fabriceci requested a review from a team as a code owner July 6, 2021 13:51
@fabriceci fabriceci force-pushed the fix-2d-moving-platform branch from 582962a to da50340 Compare July 9, 2021 14:07
@pouleyKetchoupp
Copy link
Contributor

CC @TokageItLab: since you were working on a similar solution in PR #42368, just to let you know in case you would like to participate to the discussion or do some tests.

@TokageItLab
Copy link
Member

TokageItLab commented Jul 13, 2021

I have worked on the problem #42368 before. I was able to correctly calculate the velocity on a moving slope, but I couldn't solve the edge problem, the delayed is_on_floor() decision, and the visual burial on a moving platform.

Since KinematicBody (CharacterBody in 4.0) has multiple problems, it needs to be divided into several problems, but I think there should be one final destination.

I suggest that before testing, it would be better to show the final target movement in a mockup as some video or pictures.

@fabriceci fabriceci force-pushed the fix-2d-moving-platform branch from da50340 to f64ed6b Compare July 13, 2021 09:58
@fabriceci
Copy link
Contributor Author

but I couldn't solve the edge problem, the delayed is_on_floor() decision

Could you elaborate more about that? Do you know if these problems also exist in 2D?

Note that some issues on slopes were due to a bad condition on the travel length; this was fixed recently by #49901

@TokageItLab
Copy link
Member

TokageItLab commented Jul 13, 2021

Unfortunately, I don't know much about 2D, so I'll explain about the 3D edge problem.

When a character jumps from the bottom of an object to the top, if the character's foot gets caught on the object's edge even a little bit, the is_on_floor() decision is triggered. This causes a strange snap, so I needed to make my own is_on_floor() check.

Then, I thought there are two solutions to the current Godot.

  • Use time delay to determine is_on_floor()
  • judging is_on_floor() only when the Character velocity.y value is negative

The first is not a good solution because the landing will always be delayed. The second seems to work, but has the problem that is_on_floor() will never be true forever if the jump is made on a moving-up platform.

All of this leads me to think that remove the is_on_floor()'s strange snap on the object's edge.

@fabriceci fabriceci force-pushed the fix-2d-moving-platform branch from f64ed6b to bcf0af0 Compare July 13, 2021 19:31
@pouleyKetchoupp
Copy link
Contributor

@TokageItLab I wonder if some of the problems you had in 3D were due to the fact there was no sync to physics option to get rid of the lag between the character and the platform. It would be interesting to test again with #49328 (not merged yet).

For the edge problem, maybe the second option would work if we consider the difference between the character velocity and the platform velocity?

Copy link
Contributor

@pouleyKetchoupp pouleyKetchoupp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it's ready to go, except for 2 minor things, and #50314 could be updated with the latest changes so we can merge on both 3.x and master.

#50155 now works perfectly well.
#47366 is fixed since the platform moving down is unrelated. You can open a separate issue if it's a bug from the engine.

Other issues are still fixed.

I've also tested for regression in the demo project and everything seems fine:
/~https://github.com/godotengine/godot-demo-projects/tree/master/2d/physics_tests
Functional Tests/Character - Slopes: no regression with KinematicBody2D moving on slopes.
Functional Tests/Character - Tilemap: no regression with KinematicBody2D jumping through one-way collision tiles.
Functional Tests/Character - Pixels: no regression with KinematicBody2D motion.

scene/2d/physics_body_2d.cpp Show resolved Hide resolved
scene/2d/physics_body_2d.h Outdated Show resolved Hide resolved
@TokageItLab
Copy link
Member

TokageItLab commented Jul 14, 2021

@pouleyKetchoupp Indeed, my second option may work by subtracting the platform's velocity.y from the character's velocity.y. In that case, it may be necessary to test if the character can jump on a platform that is moving down.

@fabriceci fabriceci force-pushed the fix-2d-moving-platform branch from bcf0af0 to b9ee64a Compare July 14, 2021 09:44
@fabriceci
Copy link
Contributor Author

@pouleyKetchoupp thanks for the review, changes are pushed.

@pouleyKetchoupp
Copy link
Contributor

@TokageItLab This snap on edge problem does seem like something to investigate, and probably fix in the built-in character motion. Do you have a minimal project or an issue ticket you can point me to?

@akien-mga
Copy link
Member

@fabriceci Could you amend the commit message to be a bit more explicit about what it does? "fix 2D moving platform" without more details on what this means exactly is a bit short for the git log.

The body of the message can likely be copy-pasted/adapted from the PR description which is clear enough. And I'd suggest using "Fixing 2D moving platform logic" for the commit title like for the PR.

@TokageItLab
Copy link
Member

TokageItLab commented Jul 15, 2021

@TokageItLab This snap on edge problem does seem like something to investigate, and probably fix in the built-in character motion. Do you have a minimal project or an issue ticket you can point me to?

@pouleyKetchoupp I will prepare a minimal project this weekend. Which branch should I use? Basically I'll use the master, but if there are some things I should merge, let me know.

@pouleyKetchoupp
Copy link
Contributor

@pouleyKetchoupp I will prepare a minimal project this weekend. Which branch should I use? Basically I'll use the master, but if there are some things I should merge, let me know.

Sounds great! Master is good, the latest fixes for move and slide have been merged already.

@fabriceci fabriceci force-pushed the fix-2d-moving-platform branch 2 times, most recently from b94eb55 to ec68c48 Compare July 15, 2021 09:47
Fixing by applying the movement in two steps, first the platform
movement, and then the body movement. Plus, add the platform movement
when we are on_wall.
@fabriceci fabriceci force-pushed the fix-2d-moving-platform branch from ec68c48 to fba4c9d Compare July 15, 2021 09:58
@fabriceci
Copy link
Contributor Author

@akien-mga thanks, nice catch, I didn’t pay attention to that. I also fixed the name in the doc file.

@akien-mga akien-mga merged commit 231efe0 into godotengine:3.x Jul 15, 2021
@akien-mga
Copy link
Member

Thanks!

@fabriceci fabriceci deleted the fix-2d-moving-platform branch July 15, 2021 11:51
@JosiahJohnson
Copy link

JosiahJohnson commented Jan 1, 2022

I believe this fix caused an issue where my player no longer gains any height when jumping from a falling platform. It works on 3.3.4, but not on 3.4. I also tried 3.4.2, which didn't work.

The player and block are both kinematicbody2ds. Even if I change the block to move by position instead of move_and_slide, and enable sync to physics, it makes no difference. Thanks.

jump

Edit: Here's a simplified version of my jumping code, and a comparison of the players velocity on normal jumps vs falling jumps. On 3.3.4 the print outs are identical.

func _physics_process(_delta):
    if inputAction == "jump":
	motion.y = JUMP_HEIGHT

    motion.y += GRAVITY
    motion = move_and_slide_with_snap(motion, snap, UP)

motionY

Edit 2: I figured out if I subtract the velocity of the platform, it works like previous versions. I'm guessing this is intended?
motion.y = JUMP_HEIGHT - get_floor_velocity().y

@akien-mga
Copy link
Member

@JosiahJohnson I discussed this with @fabriceci who confirmed that you need to subtract the platform's velocity now if you don't want it to affect the character controller. In 4.0 there's a property that lets you customize if and how the platform velocity should affect the character, but it's not in 3.x.

image

@JosiahJohnson
Copy link

@akien-mga Thanks for confirming. Are there any plans for adding the property to 3.x? I assume this might be preferred behavior on a lot of platformers, and the workaround isn't very obvious (at least for me :)

@akien-mga
Copy link
Member

I don't know, @fabriceci and @pouleyKetchoupp are a lot more up-to-date on feature parity between 3.x and 4.0 than I am.
If the feature can be backported easily, that would make sense IMO.

@fabriceci
Copy link
Contributor Author

@JosiahJohnson @akien-mga I backported the feature to 3.X. I hesitated to change the default for 3.X to never, but it's not ideal either, because when the platform goes up too quickly you can't jump (without the impulsion).

In your case try the second option: "upward only" or stick with "never" and customize the behaviour in code.

@JosiahJohnson
Copy link

@fabriceci Thanks, I think that will be useful. In my case it basically reversed how jumping worked, so I'd probably use "never". My upward moving platforms don't move too fast, so it's not a problem. But if I don't subtract the velocity, he does a moon jump.

@fabriceci
Copy link
Contributor Author

fabriceci commented Jan 6, 2022

he does a moon jump.

It's definitely an earth jump, but I understood what you meant :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants