I am trying to make a ball bounce off (and also sideways) when it gets into contact with another object. I am having an issue shown in the image below, where the ball rests on the triangle instead of falling off sideways. I tried playing round values for the bounciness and friction, but that didn't solve my issue. How can I solve this issue. I've added the inspector settings on the ball.

enter image description here enter image description here

  • \$\begingroup\$ Try spawning the ball with a very small decay of x,z as random(-1, 1) \$\endgroup\$ Sep 4 '17 at 3:29
  • \$\begingroup\$ @CedricMartens I don't really understand how to spawn the ball as you recommended. I would appreciate some further explanation. \$\endgroup\$ Sep 4 '17 at 3:49
  • 1
    \$\begingroup\$ Surely that is the correct physics behavior. If a ball falls exactly on a pin it will balence. I think cedric is suggesting making it not quite exactly land on the pin but off to one side slightly \$\endgroup\$ Sep 4 '17 at 8:47
  • \$\begingroup\$ Yes, @RichardTingle points out exactly what I meant. If a ball falls exactly on the point, being balanced is the correct behavior. So if you want it to fall randomly, you need to move it slightly \$\endgroup\$ Sep 4 '17 at 21:49

You can add a little randomness into your physics like so:

// Populate this with how much you want to nudge the ball.
public float jitterAmount = 1f;

// Populate this with a layer ID that identifies your triangles to bounce off of.
public int pinLayer;

// Populate this in the Inspector or in Start to point at the ball's Rigidbody2D
Rigidbody2D myBody;

void OnCollisionEnter2D(Collision2D collision) {
    if(collision.otherGameObject.layer != pinLayer)
        return; // Only jitter sideways off the pins, not other balls / the floor.

    if(Mathf.Abs(myBody.velocity.x) >= 1f)
        return; // Object already has substantial sideways motion.

    Vector2 normal = collision.contacts[0].normal;

    if(Mathf.Abs(normal.x) > 0.01f)
        return; // We've fallen onto a slope that doesn't need help.

    // Add a little nudge left or right:
    myBody.velocity += jitterAmount * (Random.value > 0.5f ? Vector2.right : Vector2.left);

You can also do this in OnCollisionExit to catch bounces that exactly cancel the incoming horizontal velocity. Here I used OnCollisionEnter to catch non-bouncing collisions too, where the ball falls and rests on the pin.

  • \$\begingroup\$ It solves my issue when jitterAmount > 1f at times, but at times it doesn't. From my observation, it doesn't work when the ball's xPosition and the triangles are extremely close (in some cases correct to several digits) to each other. I am thinking of a way to factor that into your solution. Any ideas? \$\endgroup\$ Sep 5 '17 at 15:23
  • 2
    \$\begingroup\$ It could be that we're falling ever so slightly to one side of the triangle, and half the time we apply a sideways velocity straight into it which is then opposed & neutralised by the collision. Can you check what kinds of collision normals you're getting in these situations? If they have a lean to them, we can amplify that. Else we might need to make our decision based on the point of contact. \$\endgroup\$
    – DMGregory
    Sep 5 '17 at 15:27
  • \$\begingroup\$ Sorry, I know might be out of the scope of this question, but I've not found anything quite straightforward from a Google search and forum searches. How do I find collision normals? \$\endgroup\$ Sep 5 '17 at 15:51
  • \$\begingroup\$ collision.contacts[0].normal \$\endgroup\$
    – DMGregory
    Sep 5 '17 at 15:53
  • 4
    \$\begingroup\$ How can the contact normals help me solve this issue? \$\endgroup\$ Sep 5 '17 at 17:45

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.