Physics: Differentiating different force sources separately (Rigidbody controller)

Hello,

I’m trying to make a Rigidbody player controller that has full interaction with all in-game physics.
Turns out this is incredibly complicated and difficult to do properly! All the existing examples out there have several things wrong with them that I’m having a hard time fixing.

The problem is that the only way to get satisfactory player movement using a Rigidbody is by using a target velocity, then applying forces to reach that velocity. Unfortunately, this means that as soon as any external world physics act upon the player (ie hits a spinning wheel which should launch him, or something bouncy, or even trying to maintain momentum off a moving platform), all momentum is lost, because the controller immediately applies a Force to counter-act the player’s current velocity, to bring it in line with the player’s input.

This is unrealistic and highly undesirable in my physics-based game.

I thought of a possible solution: create a “ghost” Game Object which is tied to the player’s input as usual. It moves around using the targetVelocity forces but is invisible.

Then, to move the player, simply add the current Vector3 velocity of that “ghost” object to the player’s current velocity.

Unfortunately, this will of course just results in the overall velocity stacking on top of itself forever. Even though the “ghost” object’s maximum velocity is limited, the player’s speed will be (current speed + ghost speed) - so the player will just keep speeding up.

I cannot limit the maximum speed of the player, because I want external forces to allow him to be pushed by something in the world very fast.

I want the external force to push him fast, then as its force “wears off” by friction, drag, gravity, etc, slowly come to the velocity of only the input (ghost object).

So I really just want a way of scripting this: “The player’s current velocity is equal to the player’s input velocity PLUS velocity incurred via external forces BUT NOT velocity incurred via previous player input acceleration.”
To do this, I need some way of interrupting the PhysX engine to check what the source of a force was, then only apply forces to objects once that has been checked and factored into the calculations.

How can I do this?

As detailed as the question is, it does not cover what you are trying to accomplish. A generic RB controller can take on many forms. And no, Velocity controlled “controllers” are not the only way to go. You can of course use Physics based controllers (addForce and the like) to achieve the same result.

having a “Ghost” is a great idea if you always want your player to be “upright” Simply position the non collider portion of the player at the point of where the ghost is. Gathering forward direction is will be the hardest, though, you could also simply put a limiter on the angular X and Z velocity’s in a fixed update to prevent it from tipping. This would allow you to spin as normal, but never flip.

You could apply a Weeble affect by simply Lerping the up vector back to world up and still maintaining the Y look vector.

Lerping the current angular and normal velocities to a player introduced control is also a method.

I really think that you want a highly controlled object, for that, you need alot of little handlers in there to prevent certain types of movement.

Sorry - let me try to clarify.
The only thing I want to try to do right now is the part I’ve added in bold to the above post.

I’m already using addForce to move the character. It’s just that the amount of addForce is calculated from (target velocity - current velocity).
From what I can tell from experimenting, this really is the only way that feels right (ie most like a Character Controller), because otherwise, applying a linear, impulse, or acceleration Force, the player moves more like a sliding object (or race car) than a walking person who can start, stop, change directions very quickly.

Staying upright is not a problem. It’s a 2D sidescroller game and I’m just locking rotation.

You need to accept that realistic physics very rarely feel right for player controls and you can get into the costly exercise of implementing more and more physics detail.

It is typically best to think about what you want it to look and feel like, then set about implementing that. For example a platform is generally best implemented by parenting the character to the platform.

For your specific question why don’t you set velocity to 0, then apply the large “bouncing” force?

You should also cap your (target velocity - current velocity) to some reasonable limit.

Another possibility is to have a small period of time after one of these “bounce” interactions where character controller forces aren’t applied.

Tried this. Works OK but the movement was jerky and not great.
Fixed that by using a RayCast to get the current velocity of the platform underneath, and instead of parenting, just adding that velocity to the player velocity.
Unfortunately, all momentum is lost as soon as the player jumps off the platform. Breaks basic Newtonian physical laws. That is the type of thing I am trying to fix here. Incidentally, conserving momentum properly would also totally negate the need to add the platform velocity to the player - and that’s the direction I want to go, so I don’t have to write a special script (which will never quite be realistic) to every single physical thing which might affect the player.

This makes the most sense in a lot of ways, but unfortunately, I need the player to still have control of the character in mid-air. So it needs to be the bounce force momentum + player input velocity.

I think you are heading down the path I mentioned :slight_smile: You talk about realistic physics yet you want the player to be able to move in mid air… are they equipped with a jetpack or wings? If yes are you accurately modelling your wing mechanics … :stuck_out_tongue:

Again I think you need to focus on what you want it to look and feel like. Not trying to be negative, I’ve just been down the same path myself!

For the bounce force, a very small amount of time when the player can’t control (e.g. 200ms) plus a capping of maximum force the character controller can apply should be able to reproduce what you want.