Posts: 3
Threads: 1
Joined: Sep 2020
Reputation:
0
10-09-2020, 10:20 PM
(This post was last modified: 11-09-2020, 01:23 PM by adscott1982.)
I have been struggling in my soccer game to accurately model the physics of a soccer ball.
Unfortunately the physics for a sphere object that come with Unity don't model the ball accurately enough. There is only a very tiny contact point on the sphere collider when it comes into contact with another collider. This means that if there is any spin on the ball, or it hits a surface hard, the physics don't behave anywhere near accurately.
So the solution would be to use softbody physics for the ball. This would mean when it bounces with another collider the ball would deform slightly pressing more contact points against the other collider. Hence if the ball was spinning, if it bounced harder there would be a greater effect on the ball, than if it bounced more lightly.
However in the videos I have looked at for Obi, I cannot see any sphere examples with the rigidity that you would see in a soccer ball. In most cases it would only deform very slightly, only deforming to a larger extent when hit very hard.
From everything I have seen Obi looks incredibly well made, so it would probably be OK - I just want to know beforehand if possible before I pay on the Asset Store.
See a video below for a soccer ball being kicked very hard in slow motion, and see how limited the deformation is, and how quickly it returns to its normal shape. This is the kind of rigidity I am trying to model.
If you look at this video, the deformation when kicked is barely noticeable.
https://youtu.be/mbo2_h1mAG8
Final thing, I am not trying to have a 'simulation' level of accuracy here, just enough that for the most part the football appears to be behaving as expected. The game I am making is a fun party game, not a AAA FIFA competitor.
Posts: 6,347
Threads: 24
Joined: Jun 2017
Reputation:
400
Obi Owner:
10-09-2020, 10:57 PM
(This post was last modified: 10-09-2020, 10:58 PM by josemendez.)
Hi there,
Its not entirely clear to me what is it that you want to simulate. On one hand, you express interest on accurate deformation, but in a real soccer ball this deformarion is so slight and the ball recovers from it so fast, that for all intents and purposes it can be modeled as a rigidbody. Most AAA soccer games do just that.
Using physx (unity’s built in engine), the contact area between objects is modeled as a contact manifold, which is a non-zero area. In the case of spheres i’m not entirely sure if it’s simplified as a point, though. Bouncing is modeled using a restitution coefficient (like in most rigidbody engines) which is usually enough for most purposes where actual material deformation is not needed.
A typical soccer ball can be simulated using physx just fine, in fact I used it for a side project. Only things I needed to add were angular friction and magnus effect, but these are very specific to soccer and even Obi does not model them.
So if what you’re after is accurate deformation, Obi can do it (even quite rigid objects). But in the case of soccer, rigidbodies will get you closer to the real behavior as ball deformation is mostly negligible and its visible effects on collision response are already accounted for in any rigidbody implementation. Unless you’re going for very cartoon-esque, exaggerated deformation, I’d stick with rigidbodies.
Posts: 3
Threads: 1
Joined: Sep 2020
Reputation:
0
11-09-2020, 12:11 PM
(This post was last modified: 11-09-2020, 12:12 PM by adscott1982.)
Thank you for going into so much detail.
The problem I found with using a normal rigidbody, was that the spin on the ball, and the effect on the ball when bouncing with spin was very inaccurate. I spent a lot of time trying to resolve this in code to get it to behave more accurately, and it is improved to some extent, and yet there are still noticeable problems. I have included the code below if you are interested, it too a long time tinkering to try and get it to behave more or less realistically, but it feels hacky, and I would much rather simulate the whole thing in a non-hacky way.
Additionally, when the ball is rolling along the ground, it does not come to rest properly, it will just keep rolling indefinitely in some cases. When the ball is in the air it makes sense to have a slight angular drag, but on the ground it should come to rest more quickly depending on the friction of the surface. None of this works properly for the sphere rigidbody in my experimentation. This is why I mention that I thought the sphere rigidbody must have a tiny contact point, otherwise the friction when rolling along surfaces would make a difference.
Code: private void DoCollision(Collision collision)
{
var contact = collision.contacts[0];
// Get the rotation of the ball with respect to the collision normal, and its effective speed in units per second
var forwardRotation = Quaternion.AngleAxis(90, -contact.normal) * this._rb.angularVelocity;
var rotationsPerSecond = forwardRotation.magnitude / (2 * Mathf.PI);
var rotationUnitsPerSecond = rotationsPerSecond * this._circumference;
// The velocity of the ball when projected onto the normal plane
var projectedVelocity = Vector3.ProjectOnPlane(this._rb.velocity, contact.normal);
var collisionVelocity = Vector3.Project(this._rb.velocity, contact.normal);
// The rotation direction with respect to the collision normal plane
var temp = Vector3.Cross(contact.normal, forwardRotation);
var relativeRotationDirection = Vector3.Cross(temp, contact.normal).normalized * rotationUnitsPerSecond;
var vectorDifference = relativeRotationDirection - projectedVelocity;
// Distribute the angular/velocity difference between the angular and normal velocity, incorporating some energy loss
var staticFriction = collision.collider.material.staticFriction;
var scaledVelocity = vectorDifference.ScaledUniformly(0.2f * staticFriction);
var scaledRotationUnits = vectorDifference.ScaledUniformly(-0.8f * staticFriction);
var scaledRotationRadians = scaledRotationUnits.ScaledUniformly((2 * Mathf.PI) / this._circumference);
var scaledRotationRadiansCorrected = Quaternion.FromToRotation(relativeRotationDirection, forwardRotation) * scaledRotationRadians;
var scaledRotationAngularVelocity = Quaternion.AngleAxis(-90, -contact.normal) * scaledRotationRadiansCorrected;
this._rb.velocity += scaledVelocity;
this._rb.angularVelocity += scaledRotationAngularVelocity;
// Apply collision friction
var dynamicFriction = collision.collider.material.dynamicFriction;
this._rb.angularVelocity = this._rb.angularVelocity.ScaledUniformly(1 - dynamicFriction);
// TODO: Increase force of friction when the collision velocity is high
Debug.DrawRay(this.transform.position, relativeRotationDirection, Color.red);
Debug.DrawRay(this.transform.position, projectedVelocity, Color.blue);
Debug.DrawRay(this.transform.position, collisionVelocity, Color.cyan);
Debug.DrawRay(this.transform.position, vectorDifference, Color.yellow);
Debug.DrawRay(this.transform.position, contact.normal, Color.green);
}
Posts: 6,347
Threads: 24
Joined: Jun 2017
Reputation:
400
Obi Owner:
11-09-2020, 12:28 PM
(This post was last modified: 11-09-2020, 12:34 PM by josemendez.)
Hi,
Even if spheres had a large contact patch against other objects, the fact that they are in contact during a very small amount of time when hit/bouncing (usually a single timestep) would negate any benefits of this, since you'd still have to resolve the contact in a single timestep. Contact surface area would not give you much additional information to aid in accurate angular velocity treatment, and you already have contact penetration depth available (btw, with penetration depth, you could even calculate contact area analytically in the case of sphere/plane contact if you wanted to).
The thing you want to simulate here is the effect of angular velocity on contact separation velocities, and to the best of my knowledge this can be done quite accurately even with a single contact point.
This behavior you refer to:
Quote:when the ball is rolling along the ground, it does not come to rest properly, it will just keep rolling indefinitely in some cases
Is what angular friction (aka rolling friction) is designed to avoid. The idea behind this is that surfaces aren't perfectly smooth, so a rolling ball on the ground would eventually come to a stop due to micro-imperfections in the surface. In case of a soccer pitch (grass), these micro-imperfections are actually quite "macro", so the effect is more pronounced. It's usually implemented as a torque that counters angular velocity, by an amount dependant on the material friction and relative velocity of the involved bodies at their contact point. If you look for research articles on granular materials (sand, gravel), you can find info about that as they usually implement it.
Note that Obi does not model any of this either for the softbody case. More specifically, we do have rolling friction but only for granulars, which do not have restitution (bouncing).
All of it is very specific to the soccer use case. So still, rigidbody simulation will get you closer to your goal. Sure, there's some simplifications done by PhysX that result in lacking simulation, but imho re-adding them in some way is your best bet.
Posts: 6,347
Threads: 24
Joined: Jun 2017
Reputation:
400
Obi Owner:
11-09-2020, 12:39 PM
(This post was last modified: 11-09-2020, 12:40 PM by josemendez.)
Here's an article that details proper rolling friction implementation for a contact between two objects (see section 4.3):
https://www.researchgate.net/publication...d_Approach
Posts: 3
Threads: 1
Joined: Sep 2020
Reputation:
0
Thank you so much for all the help and detail!
|