I know my code is ugly, I welcome any improvement suggestions. My goal seems simple, spawn 75 “bubbles” (prefabs) on the screen in random positions at random rotations, and have them move with a random velocity between 0.3 and 0.7, or -0.3 and -0.7. When they collide with a wall, calculate a new random velocity of the same range with respect to which wall it hit.
Currently how I am doing this:
-
GameManager object has a script that instantiates the bubbles
-
Bubble prefab has a script that sets the velocity.
How I IMAGINED it going: When the prefab script executes, the start routine would determine an initial random velocity. Then, the OnCollisionEnter2D would be called when the bubble hits a wall and it would recalculate a velocity going in whatever opposite direction the wall is (if it hits the bottom wall, set velocity to a random positive Y value, if it hits the right wall, set velocity to a random negative X value, etc).
How it is ACTUALLY going: Debug logs show the OnCollisionEnter2D executing before Start. This is causing bubbles to get “stuck” in the corner of the screen, and other unexpected behavior. See image attachment of Bubble #70 it is stuck in the bottom left corner with the Rigidbody showing a velocity of 0,0. Debug Log shows the velocity was first calculated in the collision routine, then last calculated in the Start method as -0.7, -0.7. Obviously being stuck in the bottom left, it can’t go any lower so it froze it to 0,0. This wouldn’t have happened if Start had run first and THEN the OnCollisionEnter2D because the collision routine would have detected the bottom walls and set the velocity to a positive value. Now that it’s stuck, it can’t collide again.
I’m not sure what to do, I can put something in Start to check the position first, but I feel like I have a bigger problem with my code running the OnCollisionEnter2D before Start, and that would only be a bandaid.
GameManager script to instantiate bubble prefab:
void Start() {
buffer = 10f;
objectCount = 75;
for (int loop = 0; loop < objectCount; loop ++){
worldMin = Camera.main.ScreenToWorldPoint(new Vector2(buffer, buffer));
worldMax = Camera.main.ScreenToWorldPoint(new Vector2(Screen.width - buffer, Screen.height - buffer));
spawnPosition = new Vector2( Random.Range(worldMin.x, worldMax.x), Random.Range(worldMin.y, worldMax.y));
GameObject newGO = (GameObject)Instantiate (objectToSpawn, spawnPosition, Quaternion.Euler(new Vector3(0, 0, Random.Range(-40.0f, 40.0f))));
newGO.name = newGO.name + loop;
}
}
Bubble prefab script to set velocity (my reason for the if statements are because if the velocity random value is very close to 0 the object moves TOO slow):
void Start()
{
Physics2D.IgnoreLayerCollision(gameObject.layer, gameObject.layer);
min = -0.7f;
max = 0.7f;
compareMax = max - 0.4f;
compareMin = min + 0.4f;
moveX = Random.Range(min, max);
moveY = Random.Range(min, max);
if (moveX < 0.0f && moveX > compareMin){
moveX = min;
}
if (moveX > 0.0f && moveX < compareMax){
moveX = max;
}
if (moveY < 0.0f && moveY > compareMin){
moveY = min;
}
if (moveY > 0.0f && moveY < compareMax){
moveY = max;
}
Debug.Log("Start name: " + gameObject.name + ", moveX: " + moveX + ", moveY: " + moveY);
rb = GetComponent<Rigidbody2D>();
rb.velocity = new Vector2(moveX, moveY);
}
void OnCollisionEnter2D(Collision2D col){
rb = GetComponent<Rigidbody2D>();
if (col.gameObject.tag == "Border"){
min = -0.7f;
max = 0.7f;
compareMax = max - 0.4f;
compareMin = min + 0.4f;
moveY = Random.Range(min, max);
moveX = Random.Range(min, max);
if (col.gameObject.name == "BottomWall"){
moveY = Random.Range(compareMax, max);
}
if (col.gameObject.name == "TopWall"){
moveY = Random.Range(min, compareMin);
}
if (col.gameObject.name == "LeftWall"){
moveX = Random.Range(compareMax, max);
}
if (col.gameObject.name == "RightWall"){
moveX = Random.Range(min, compareMin);
}
Debug.Log("OnCollision name: " + gameObject.name + ", moveX: " + moveX + ", moveY: " + moveY);
rb.velocity = new Vector2(moveX, moveY);
}
}
