# Momentum-wise accurate player controls in Unity regarding collisions

First post here. So I am a newbie to Unity and am willing to create a general character controller script to base my future characters. I understand a character's mechanics are pretty design (UX) dependent and I will need a few varients.

## What I want

Momentum-wise accurate physical simulation (as much as game performance allows). Some examples:

• If a flying canon-ball hits the player, it shall be crashed or flown away (some parameters would let us kill him in code hopefully) in accord with ball's momentum and player's mass.
• If the player hits a stationary canon-ball the ball most-probably wouldn't move (due to friction), yet if they push enough it gains some torque and rolls-over. Rotational and kinetic energy would need equal energy provided.
• Multiple player's could act upon a bunch of pieces just for fun.
• Regular character capabilities such as stair/ladder climbing, walking, etc.

## What I have read so far:

• CharacterController needs to write code for desired physics, and apt when not so interactive characters (e.g. first person shooter) are at hand.
• Rigidbody is good for non-agent dynamic items (e.g. falling boxes), and is hard to implement for agents (muscle powered humanoids, etc.), though possible.

How can I implement such momentum-wise accurate physics (regarding collisions) in Unity engine?

• I don't see how implementing accurate physics for CC would be any different than using rigidbody. Compared to re-implementing physics, molding rigidbody into an agent is certainly not hard. Apr 3, 2021 at 17:37

The way I like to solve this is to use a dynamic Rigidbody, and give my character control script a notion of "traction" - the maximum force they can exert against the ground to alter their movement.

When traction is high, we can control the movement very precisely, like using a CharacterContoller. Imagine the character is wearing sturdy cleats with a planted stance so they can resist attempts to push them around.

External influences can still be used to modify this traction where we want to: for instance, we can check the material of the collider under the controller and use it to lower the current traction if, say, we're standing on slippery ice.

Or if the character is hit, we can put them into a stumbling state where they have reduced traction for a period of time, or until they drop below a certain speed, allowing strong hits to send them sliding/flying like a regular dynamic object.

The heart of this is a helper method something like this:

void PushToward(Vector3 targetVelocity, float maxStartingForce, float maxStoppingForce) {

Vector3 deltaV = targetVelocity - rigidbody.velocity;

Vector3 force = rigidbody.mass * deltaV / Time.deltaTime;

// TODO: You may want to remove the component of force perpendicular to the
// terrain, so that we can only push ourselves parallel to the ground.

float forceLimit = Vector3.Dot(deltaV, rigidbody.velocity) < 0f ?
maxStoppingForce : maxStartingForce;

force = Vector3.ClampMagnitude(force, forceLimit);


Here we pass the velocity our character "wants" to have based on the player's input, but modulate that want according to a limiting force value (you could also parametrize these as accelerations instead of forces, to take the mass out of the equation). That way our control script respects some physical limits of how much "torque" our character's engine has, how much grip they have on the ground, how hard they can push against obstacles/etc. In contrast to a CharacterContoller that will always go exactly to the destination position, stopping only for collisions.
These two force parameters become our avenue for managing our character's traction. When standing on ice, or when the character is in a stumbling/ragdoll state, (which we can trigger based on relative velocity/impulse of a collision inside OnCollisionEnter), we can scale both these force limits down to a small multiple, so the character exerts less and less control over their movement. Maybe even 0 to send them skating like a hockey puck. Then we can bring that multiplier back up to 1 when they're on solid ground or when they regain their footing after a knock back.