Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Is the softbody asset a good choice for modelling a soccer ball? [Answered]
#3
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);
    }
Reply


Messages In This Thread
RE: Is the softbody asset a good choice for modelling a soccer ball? - by adscott1982 - 11-09-2020, 12:11 PM