# [Solved] [Unity Physics] Help needed to understand the correct way to use ApplyImpulse

Discussion in 'Data Oriented Technology Stack' started by RBogdy, Jun 5, 2019.

1. ### RBogdy

Joined:
Mar 6, 2019
Posts:
60
Hello,

As I'm learning the new ECS ways, I thought it would be fun to replicate a bowling game. Unfortunately I ran into problems when using the Unity Physics ApplyImpulse() function; the ball just 'jumps' from the floor instead of launching forward and I can't tell why.

From the beginning:

I made some sort of slingshot mechanism using the 'MousePickBehaviour' script as an example, so I ended up with 2 systems:

1. Begging of the shot - updates a component native array copy with a start position (from a mouse click), does a ray cast job to get the entity touched at the start position and calculates the point in world, body from world and point on body (pretty much copy/paste from 'MousePicker')
2. End of the shot - updates a component native array copy with the end position (from a mouse release) and the difference between start and final points

A 3rd system is used to apply the impulse on the ball and this one was inspired by the PhysicsExamples Demo number 5 - Apply Impulse case
So this 3rd system receives references to the above mentioned systems and replicates the same behaviour as 'LinearDashpotBehaviour' script and at the end applies an impulse.

The problem is that the ball 'jumps' and is not sliding on the 'floor'.

Force calculus:
Code (CSharp):
1. var deltaX = EndPosition.x - StartPosition.x;
2. var deltaZ = EndPosition.z - StartPosition.z;
3. var strenght = sqrt(deltaX * deltaX + deltaZ * deltaZ);
4. var direction = mouseStartPosition - mouseEndPosition;
5. var force = 5.0f * strenght  * (direction / sqrt(lengthsq(direction)));
6.
Relevant calculus in system no 3:
Code (CSharp):
1.
2. int rigidBodyIndex = world.GetRigidBodyIndex(StartSystem.ShotStartDatas[0].Entity);
3. RigidBody rb = rigidBodyIndex >= 0 ? world.Bodies[rigidBodyIndex] : RigidBody.Zero;
4. var pos = math.transform(rb.WorldFromBody, StartSystem.ShotStartDatas[0].PointOnBody);
5. var linearV = world.GetLinearVelocity(rigidBodyIndex);
6. var impulse = EndSystem.ShotEndDatas[0].Force + 0.5f * linearV;
7. world.ApplyImpulse(rigidBodyIndex, impulse, pos);
8.
PS: When I change the world.ApplyImpulse to world.SetLinearVelocity I get the behaviour I want (the ball slides) however there's no angular movement (as expected in linear velocity)

Last edited: Jun 5, 2019
2. ### Shinyclef

Joined:
Nov 20, 2013
Posts:
379
``var direction = mouseStartPosition - mouseEndPosition;``

If this comes from raw mouse data, then this will x/y floats right?
It feeds into 'force' without any axis changes.

``var impulse = EndSystem.ShotEndDatas[0].Force + 0.5f * linearV;``

It would jump if the mouse moved in y position.

Perhaps you want to take the mouse/force y and use it as a 'z' impulse?
Not sure if my assumptions about the rest of your code are accurate, and I have no comment or assumptions on the behaviour of 'world.ApplyImpulse'.

3. ### RBogdy

Joined:
Mar 6, 2019
Posts:
60
I'm doing the 'Camera.main.ScreenToWorldPoint(new float3(mousePosition.x, mousePosition.y, Camera.main.transform.position.y))' conversion before sending it to the component copy array for both the initial and final position.

I did a debug Log for the Force before sending it to ApplyForce and I get values such as:
float3(-11.10921f, 0f, 35.31141f),
float3(-17.19282f, 0f, 17.06057f), etc.

So there is no Y value when the force is sent to ApplyForce, however my 'Object' jumps from the floor. Any ideas why that might happen?

As I said before, world.SetLinearVelocity sends the 'Object' gliding as it's supposed to, with no Y movement.

4. ### RBogdy

Joined:
Mar 6, 2019
Posts:
60
The root cause of the problem was the point at which I chose to Apply the impulse. After some maths and thinking I got it to work properly.

Shinyclef likes this.
unityunity