godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

RigidBody physics test step or calculate test collision #740

Open Garbaz opened 4 years ago

Garbaz commented 4 years ago

Describe the project you are working on:

A game with bouncy grenades being shot from a grenade launcher.

Describe the problem or limitation you are having in your project:

I would like to display the predicted trajectory of the grenade before shooting it. This requires somehow getting the flight path of a RigidBody (including bouncing of other PhysicsBodys) over many physics steps, but in one frame.

Describe the feature / enhancement and how it helps to overcome the problem or limitation:

This could be solved by allowing stepping the physics of the whole world manually many times in one frame. This probably would not be practical though, because resource intensive.

What would be very helpful thought, is a way to calculate the physics of a RigidBody with the world manually. Either a function that runs a full time step for the RigidBody, returning the position,velocity,etc (Maybe as a PhysicsDirectBodyState?) it would have after the step.

Or, since PhysicsDirectSpaceState.cast_motion() already exists, it would be sufficient to have a function that, given a certain collision, returns how it would change it's physics state.

Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams:

# As member of RigidBody (don't know what a good function name would be)
# override_bodystate - a way to pass in a different physics state (e.g. from previous test step),
#                      takes the RigidBody's current "real" physics state if null.
# delta - How big a time step should be calculated, defaulting to the PhysicsServer's time step. 
PhysicsDirectBodyState physics_test_step(override_bodystate : PhysicsDirectBodyState = null, delta: float = 0.01667):
    # Calculate movement of RIgidBody
    # Check for collisions with world
    # Calculate changed physics state, as if this collision would occur "for real".
    # Return new physics state

If this enhancement will not be used often, can it be worked around with a few lines of script?:

No, at least not to my knowledge, my attempt at doing this manually was a lot of code, didn't work perfectly and required a bunch of assumptions about the RigidBody, essentially replicating internal physics code (poorly).

Is there a reason why this should be core and not an add-on in the asset library?:

Since this necessarily would be integrated with the physics engine, I don't think this can be done as an add-on.

Xrayez commented 4 years ago

I'm doing a very similar thing in 2D and stumble upon exact problem!

Have you read this article on solving ballistic trajectories? I ended up going for math way because I also need to solve for either launch angle, power, or even time, and because in some cases I have to use KinematicBody2D (doesn't suffer from CCD issues godotengine/godot#9071 as it can be controlled manually).

Or, since PhysicsDirectSpaceState.cast_motion() already exists, it would be sufficient to have a function that, given a certain collision, returns how it would change it's physics state.

I have a proposal regarding implementing a ShapeCast node #710, according to your snippet I think it could simplify the code to some extent.

What I also imagine is some sort of BallisticCast node which could use a shape and a PhysicsDirectBodyState to check for collisions that way. That's certainly a plugin territory but I'm certain the engine could provide some API to make this easier I hope...