0
\$\begingroup\$

So im trying to build a visual physics simulator that I intend to use at work to help some of my students understand how various forces interact within multi particle systems. I also want them to see how computational physics is done, and so want to code some physics into unity as opposed to use the pre-installed physics systems.

So I have a bunch of Spheres on my 2D plane which are acting as my particles - they have charge and mass. Im calculating the Coulomb Force that each particle acts upon one another, which gives a Vector2, where x is the magnitude of the force, and y is the angle the force acts. This all works perfectly I think:

force = (coulombConstant * particleCalculating.getCharge() * particleApplying.getCharge()) / (distance.magnitude * distance.magnitude);
angle = Mathf.Atan(distance.x / distance.y);

(except for some powers which I will sort out later, this works fine)

Then, the idea is to sum all these forces together as such:

foreach (Vector2 particle in forces)
{
    netXForce += particle.x * Mathf.Sin(particle.y);
    netYForce += particle.x * Mathf.Cos(particle.y);
}

Then I apply this to get an acceleration, and generate a velocity and move the particle.

Which should all work... the problem is the unity angle system (or my use of the unity angle system, whichever you prefer :)). I cant get it to differentiate from 0.5 rad to the bottom left and 0.5 rad to the top right (for example). This means two particles repelling one another actually add to each others acceleration a they are trying to go in opposite directions.

Any help here would be great - even if its just a description of why the unity angle system is great :)

\$\endgroup\$
1
\$\begingroup\$

This isn't a problem with Unity, this is a problem with using the wrong math function for the job.

As you'll remember from high school math class, the tangent of an angle repeats with a period of \$\pi\$:

Tangent graph from Wolfram MathWorld - http://mathworld.wolfram.com/Tangent.html

That means that in one half of the unit circle, it gives the same value as in the other half of the unit circle.

This is because the sign on the x and the sign on the y combine when you do the division:

\$\frac {-y} {-x} = \frac y x \$ & \$\frac {-y} {x} = \frac y {-x} \$

So, the right tool for this job is the 2-argument arctangent, available in most programming environments as "atan2", and Unity is no exception.

angle = Mathf.Atan2(distance.y, distance.x);

(Note here I've flipped x & y relative to your example, since in mathematical convention 0 degrees corresponds to the positive x axis and proceeds counter-clockwise as we increase the angle. This means exchanging your use of Sin & Cos)

Of course, you could skip all the trig and just work in plain Cartesian vectors rather than polar coordinates:

Vector2 GetCoulombForce(float chargeA, float chargeB, Vector2 positionA, Vector2 positionB) {
    var offset = positionB - positionA;
    float strength = coulombConstant * chargeA * chargeB / offset.sqrMagnitude;
    return offset.normalized * strength;
}

This gives the force exerted by A onto B. Negate it for the force exerted by B onto A.

\$\endgroup\$
  • \$\begingroup\$ Thanks, except for the slight dig at my forgetting tan functionality ;) Never used atan2 before either so nice to know what its for! \$\endgroup\$ – Alexander Bunting May 20 at 18:24
  • \$\begingroup\$ That was more a dig at blaming "the Unity angle system" for behaviour that's entirely within standard definitions of tan / atan. ;) \$\endgroup\$ – DMGregory May 20 at 18:27
  • \$\begingroup\$ Ah, touche ;) Thanks again for the help! \$\endgroup\$ – Alexander Bunting May 21 at 18:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.