Instantiated "ball" prefabs' physics/variables are somewhat linked?

Hi

I am been playing around with unity, and i have come across the following issue and its doing my head in even though I am not using any static variables.

I have “ball” prefab that i spawn within a little square box. the prefab has the “Ball Behavior” script attached to it. I am trying to see how its physics works such that it can reflect off the wall, limit Y axis so that it doesn’t bounce off. Everything is working perfectly when only one “ball” is spawned, once multiple “balls” are present, the forces go insane. Sometimes the “balls” speed up or reflect weirdly off the wall. See below gifs:

one “ball”:7489439--921914--bandicam 2021-09-12 17-14-27-562.gif

multiple “balls”:7489439--921917--bandicam 2021-09-12 17-15-00-069.gif

Ball spawn code: (attached to a cylinder acting as a canon placeholder with “Ball” attached as RigidBody)

public class BallSpawn : MonoBehaviour
{
public Rigidbody ball;
public int ballNameCount;
void Update()
{
if (Input.GetKeyDown(“x”))
{
Instantiate(ball);
}
}
}

Ball behavior: (attached to the “Ball” prefab)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BallBounce : MonoBehaviour
{
private Rigidbody rb;
private Vector3 lastvelocity;
private int loc;
private float vecX, vecZ;
private float sp=100f; //speed of the force applied to the ball during spawn
void Start()
{
rb = GetComponent();
loc = Random.Range(0, 4); //pick a number to spawn
//West spawn
if (loc == 0)
{
vecX = -sp;
vecZ = 0;
}
//East spawn
if (loc == 1)
{
vecX = sp;
vecZ = 0;
}
//South spawn
if (loc == 2)
{
vecX = 0;
vecZ = -sp;
}
//North spawn
if (loc == 3)
{
vecX = 0;
vecZ = sp;
}
}

void FixedUpdate()
{
if (!rb) { return; }
lastvelocity = rb.velocity;
}

void OnCollisionEnter(Collision c)
{
if (!rb) { return; }
if (c.gameObject.tag==“Ground”) // add force when the ball hits the ground after spawn
{
rb.AddForce(new Vector3(vecX, 0, vecZ), ForceMode.Impulse);
rb.constraints = RigidbodyConstraints.FreezePositionY;
}
var speed = lastvelocity.magnitude;
var direction = Vector3.Reflect(lastvelocity.normalized, c.contacts[0].normal);
rb.velocity = direction * Mathf.Max(speed);
}

}

In your collision response function you keep adding that force every time it comes in contact with the ground.

You probably think this is only happening once, but I bet it happens at almost every wall reflection because the rotation of the ball will half the time impart a slight up force, then the ball will fall again to the surface and trigger the ground contact a second time.

To prove it, put a Debug.Log() statement there.

1 Like

Thank you mate I can see the problem now, cheers for the explanation. A simple boolean fixed the problem.

void OnCollisionEnter(Collision c)
{
if (!rb) { return;}
if (c.gameObject.tag==“Ground” && !touchedGround)
{
touchedGround = true;
rb.AddForce(new Vector3(vecX, 0, vecZ), ForceMode.Impulse);
rb.constraints = RigidbodyConstraints.FreezePositionY;
}

1 Like

Like my Daddy always says, “There ain’t no problem you can’t fix with a simple boolean.” :slight_smile:

1 Like