I’m trying to simulate the tennis ball physics in a 3D tennis game.
In a real tennis game, forward spin is applied to a ball in order for it to go over the net and then fall down on the opposite site.
I’m wondering what tool in Unity I can use to achieve this in the most realistic possible way.
I’m guessing I would need to combine rotation and force or acceleration at the same time, but I can’t seem to figure out the way to do this. I’m also thinking I might be needing some geometry formula with angles.
If you could give me a hint, I would really appreciate it.
Here’s a hint: In reality, the Magnus effect is what causes a rotating object to be deflected when moving through a fluid (like air). Don’t ever let anyone tell you it’s the Bernoulli effect; this is a pet peeve of mine. Reading about Magnus force should help give you a better idea of what’s going on when topspin, backspin, or side spin effects trajectory.
In simple terms, the fluid is directed upward behind the object during a topspin, downward during backspin, etc. The reasons for this are complex, but one can imagine that since the ball is pushing the air, the air also pushes the ball, but in the opposite direction. This is true for any spin angle.
It’s a complicated effect to quantify, but I think it should be plausible to get a convincing model working that applies a Magnus force whose magnitude is based on the angular speed of the ball and the speed through the air as well as the angle between the velocity vector and the axis of rotation (I bet a sine relationship would look about right). Obviously the direction of the Magnus force would depend on the direction of rotation of ball and its direction of motion as well. For this model, I’d encourage calculating magnitude and direction independently.
If you want it to be more realistic than this, then you’d have to do some more research, but I think that this will work for you once you get it going. I might try a few things when I get home to see if I can get some of this working myself. I’ll let you know if I come up with specific formula that seems to work.
Yes, after doing some research I realized that the effect is in fact the Magnus Effect. And after watching a tutorial
“youtube]ROYdWCs4ANs”
I was very disappointed, since the guy on it says that this effect is not supported by Unity, that it is something that Unity cannot do.
However, he says it is something that can be achieved through Vector3.cross.
If this is true and Unity cannot simulate such a simple thing as a ball rotating and moving forward at the same time, then I’m not only disappointed, but I’m also wondering if I should actually continue to spend time on it or look for another engine that is more powerful. I’m surprised because everyone keeps talking about how amazing Unity is :S
I think you may be misunderstanding the video. I believe they are only saying that the Magnus effect cannot be DIRECTLY simulated, which is true.
Obviously, Unity simulates position, rotation, velocity, and angular velocity, and it does it well. It also has just about everything you’d expect from a 3D physics engine, such as collisions, friction, forces, etc.
Sorry, yes, there is a change I may have misunderstood, as I am new to Unity and game engines in general. But those are the words the guy actually used: “Unity cannot do that”. If there is a possibility to teach Unity to do whatever we want it to, then I probably would have not used that phrase.
So you mean to say we can just use real life physics formulas, “teach” them to Unity and have it make them happen on the screen as realistically as if they were its own built-in tools?
Yes, you can always use a real formula in Unity, but there will probably be limitations for all but the most simple ones. for example, Magnus forces depend on the density of the fluid, which Unity does not simulate.*
Also, I can’t say it will be as realistic as if it was built-in to Unity; it’s possible that a professionally developed model could be somewhat more sophisticated than the one I described above. However, for a tennis game, you should be able to make it realistic enough.
The basic idea is to just look at the speed and rotation of the ball, which Unity can tell you, and add your own force (Unity allows this, too) in a direction and magnitude that follows your own formula. The force will change the path of the ball. It’s your job to make a formula that makes the path change appear to be due to the Magnus effect.
*You could say that different areas in your game have different densities, and then factor density into your formula, but I’m referring to the changes in density that come with non-uniform pressure in fluids, especially when solids move through them; i.e. a projectile has compressed fluid in front of it and turbulent fluid behind it as it travels.
I have been taking a look at that Udemy course and the whole content of it seems to be aimed directly at what I’m looking for, so I think I’ll just go for the course.
After watching the video once again, I realized what he meant. He actually teaches how to make Unity do what it doesn’t do natively. And it looks like he actually even gives you the entire code for the ball to behave the Magnus effect.
the wikipedia page on Magnus effect states you can implement it as a force whose direction is orthogonal to the linear velocity and angular velocity vectors (use a cross product of these to get the direction) and whose magnitude is 4/3 * pi * air density * (ball radius)^3. You can consider air density as a spatially constant parameter, that allows you to control the intensity of the effect.
Just slap the following component onto a rigidbody ball, adjust the radius and air density, and you’re done.
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class MagnusEffect : MonoBehaviour
{
public float radius = 0.5f;
public float airDensity = 0.1f;
private Rigidbody rb;
void Awake()
{
rb = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
var direction = Vector3.Cross(rb.angularVelocity, rb.velocity);
var magnitude = 4 / 3f * Mathf.PI * airDensity * Mathf.Pow(radius, 3);
rb.AddForce(magnitude * direction);
}
}