Character Controller with no physic interaction

Hi guys,

i just started with the new unity dots physics and ran into some problems. Maybe someone has an answer :)

I used a dynamic physics body to create a third person character controller with DOTS physics.
The translational movement is done with help of the PhysicsVelocity component. The rotation is set by the Rotation Component. Gravity is holding the body on the ground and jumping is performed with an velocity impulse.

Now my problem:
My AI enemys are pushing my character when they are coming closer (physic interaction). I want that the enemys block my player but dont push the player away. (The enemys have a physics shape)

How do i get rid of the physic interaction effect between enemy and player but still keep colliding/blocking?

Maybe there is also a chance to enable/disable this behaviour in a future setting, because i think the most character controller want to collide with the enviroment but don't want to interact with it.(Like the character controller in Unity monobehaviour)

I already tried:
- Set the inverse of inertia to 0 (this helps with the rotation)
- Set the mass to a very high number (but does not help)

I saw that there is a way to modify the simulation physic world, but i have no idea how. (

1 Like

You can change the motion type on the physics body


I already tried to use a Kinematic physic body, but had no success with it.
With a kinematic body the player is not pushed away anymore (which is nice), but it ignores all collisions with the enviroment. For example running through walls or enemys. (Even falling through the ground if gravity is simulated by setting physicsvelocity.y)

As far as i know the kinematic body is more for self control of objects which don't interact with the environment, but are actuated by physicsveolcity.

Any other thoughts?

What you need to do here is tell the simulation "for interactions between these specific bodies, treat them as if they had a different mass". That is where Jacobian modification comes in - you need to modify the contact Jacobians before they get solved, so that the enemy virtually has infinte mass.

You can see an example of something like this in the following sample: Modify/ModifyContactJacobians.unity

There are 2 key parts to note in ModifyContactJacobiansBehaviour.cs:
1. Opt into mass modification by setting the JacobianFlags.EnableMassFactors flag on the contacts between your specific bodies (identifed however you like), via the PostCreateContacts callback. This simply tells the Jacobians to allocate extra memory to store the mass modification info. We don't allocate that by default because it is a rare use case.
2. Apply your mass modifications to the Jacobians by setting MassFactors for those that have HasMassFactors = true, via the PostCreateContactJacobians callback. Set InvInertiaAndMassFactorA or B to to treat that body as having infinite mass during solving for this frame.

That is the general idea anyway, hope it is clear enough to help you apply it to your use case.

1 Like

Thanks for the quick answer.

I tried to set the jacobians like the example above but had semi success.

If i set the InvInertiaAndMassFactor to then the player is no longer pushed away (like i want), but the player does not collide anymore with objects (which i dont want)

I also tried to set the InvInertiaAndMassFactor to (0,0,0,1) like in the examples, but this has no effect. (player still pushed away)

Make sure you only modify the jacobian for contacts between the player vs enemy, not for player/enemy vs other objects. Use RigidBody.Entity and/or RigidBody.CustomTags to identify when you have that pair.

PS: Setting InvInertiaAndMassFactor to (0,0,0,1) is telling it to prevent rotation but allow linear movement. You want zero in the the W component for your use case.

1 Like

I marked both enemy and player and set the InvInertiaAndMassFactor (0,0,0,0) to both if they collide.

The problem is that now both (enemy and player) no longer collide with each other. (The player can run through the enemy). What i want is that player and enemy block each other but dont add forces to each other.

You need to modify both their velocities to remove the portion of their velocity vector in the direction of the collision (it's the same as wall sliding...)

Untested regular code (sub Vector3 for float3 or whatever):

public Vector3 Slide(Vector3 velocity, Vector3 normal)
    Vector3 projected = normal * Vector3.Dot(velocity, normal);
    velocity -= projected; //might need flipping or not, test it
    return velocity;

Vector3 collisionNomal = the direction from the other character to you, normalized (or wall hit normal etc etc)
Then on collision your velocity will be: velocity = Slide(velocity, collisionNormal);

Thanks for the tip! Going to try out modifying the veolicty.

So is there a way to use Jacobians to create a blocking effect? Right now I am using CapsuleCast + computer penetration which works but Jacobians could be more elegant.

Problem with compute pen arises when you have multiple different penetrations then you have to work out where the object should end up. Because it will be pushed out along one normal penetration into another. This is a very common problem with custom character controllers. To solve this I recommend giving a temporal element for separation, but also negate the velocity along that same normal, assuming the velocity is moving toward the penetration.

This is not so different to how Physx solves.

Right now I computer penetration for each collider and take the one with the largest unpenetration distance. I also calculate my own velocity etc. totally separately from any physics.

In cases where my controller would get stuck I simply let it clip through after a timer has pasted. There may be some rare oscillatory cases where it gets screwed up, but have not noticed that yet.

What do you mean by a temporal element for separation a push back force? I know some physics engines work that way. However, I do not want a bouncy/sliding effect on my controller. In some cases, I do apply rotations. But in most cases, I have other collision avoidance systems in place. (reciprocal velocity obstacles and steering behaviors)

A push back force would mess up my reciprocal velocity obstacle code I think. I do not use RVO for static obstacles since I only use a 1D linear program that falls back to steering behaviors.