Hello,
So basically in my 2D game, I have an area on my screen where I want to spawn a bunch of ball sprites evenly, say 8 rows with each row containing 6 balls with a gap between each of them of X.
The idea is that I can change the number of rows, or balls per row, or the pixel gap between the balls to anything I want and it’ll just resize the balls to make them fit perfectly in the area. The reason for this is so that the balls will resize themselves properly depending on the size/aspect ratio of the screen.
Currently it looks like this (the darker area where the balls are, should be the area they are resized to):
I understand the conflict with the width and height in that with the orbs being circles, it likely wont math out evenly however I will settle for just them scaling properly for the width as I can try and adjust the UI to clip any extra room at the top.
In the code, what I basically do is calculate the width and height of the game area (taken from the transform.position.x & y’s of two empty objects anchord to the bottom left and top right of the game area).
With this width I minus the number of gaps between balls * the size of the gaps (6 balls = 7 gaps). This gives me the amount of space I’m able to use out of the width of the screen for the sake of ball size.
So I then take this number and divide it by the number of balls in the row.
This final number should give me the sprite size of the balls (it actually gives me 56% of the sprite size as the transform positions don’t 1:1 the sprite size for some reason) so that if each ball in the row was that size + the size of all the gaps, it would equal the width of the screen. I’m doing the same thing with the height but I’ve been focusing mostly on just trying to get the width to work.
This is the code that spawns the balls (orbs in the script):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class OrbPositions : MonoBehaviour
{
public GameObject orbParent;
public GameObject orbPrefab;
public Transform screenTopRight; // An empty object anchored to the top right of the game area
public Transform screenBottomLeft; // An empty object anchored to the bottom left of the game area
public int minX; // The minumum transform.position.x of the game area.
public int maxX; // The maximum transform.position.x of the game area.
public int minY; // The minumum transform.position.y of the game area.
public int maxY; // The maximum transform.position.y of the game area.
public float screenWidth; // The gap between the min and max transform.position.x's of the game area.
public float screenHeight; // The gap between the min and max transform.position.y's of the game area.
public Transform orbSpawnPoint; // An empty object used as transform.position spawn point.
private float startingX; // The starting transform.positon.x of the orb spawn point.
private float startingY; // The starting transform.positon.y of the orb spawn point.
//private float currentX;
//private float currentY;
public int rowsToSpawn;
public int orbsPerRow;
public float pixelGap = 31; // The number of pixels to put between each orb.
public float orbXSpacing; // The transform.position.x spacing to leave between each orb.
public float orbYSpacing; // The transform.position.y spacing to leave between each orb.
public int spriteSize = 300; // Size of the orb sprite.
void Start()
{
screenTopRight.GetComponent<Image>().enabled = false;
screenBottomLeft.GetComponent<Image>().enabled = false;
// Fetches the boundries of the game area in transform.position.
minX = (int)screenBottomLeft.transform.position.x;
maxX = (int)screenTopRight.transform.position.x;
minY = (int)screenBottomLeft.transform.position.y;
maxY = (int)screenTopRight.transform.position.y;
// Calculates the width and height of the game area based on the boundries.
screenWidth = Mathf.Abs(minX - maxX);
screenHeight = Mathf.Abs(minY - maxY);
// Some Drawlines to make sure the width and height are working properly.
Debug.DrawLine(new Vector3(minX, minY, 0), new Vector3(minX, maxY, 0), Color.red, 1000f, false);
Debug.DrawLine(new Vector3(minX, minY, 0), new Vector3(maxX, maxY, 0), Color.green, 1000f, false);
Debug.DrawLine(new Vector3(minX, minY, 0), new Vector3(maxX, minY, 0), Color.blue, 1000f, false);
print("The game width is: " + (int)screenWidth);
// Now I take the number of gaps * the size of the gaps, and minus it from the screen width.
int widthMinusGaps = (int)screenWidth - ((int)pixelGap * (orbsPerRow + 1));
print("Screen width minus the total pixel gaps (" + ((int)pixelGap * (orbsPerRow + 1)) + ") is: " + widthMinusGaps);
// Now I take what is left over, and divide it by the number of orbs in the row.
int remainderDevided = widthMinusGaps / orbsPerRow;
print("The reaminder divided by the number of orbs in the row is: " + remainderDevided);
// The remainder divided should be 56% of what the sprite size of the orb should be set as.
print("Sprite size should be: " + (int)(remainderDevided / .56f));
spriteSize = (int)(remainderDevided / .56f);
// Ignore this //orbXSpacing = ((screenWidth - ((orbsPerRow + 1) * pixelGap)) / orbsPerRow) + pixelGap + (spriteSize / 2);
orbXSpacing = pixelGap + spriteSize;
orbYSpacing = pixelGap + spriteSize;
startingX = screenBottomLeft.transform.localPosition.x + ((spriteSize / 2)) + pixelGap;
startingY = screenBottomLeft.transform.localPosition.y + (spriteSize / 2) + pixelGap;
orbSpawnPoint.localPosition = new Vector3(startingX, startingY, 0);
SpawnOrbs();
}
private void SpawnOrbs()
{
ResetPositions();
for (int rts = 1; rts < rowsToSpawn + 1; rts++) // For rows to spawn (rts)
{
for (int opr = 1; opr < orbsPerRow + 1; opr++) // For orbs per row (opr)
{
GameObject newOrb = Instantiate(orbPrefab, orbParent.transform);
newOrb.name = "Orb Point. Row: " + rts + ". Column: " + opr + ".";
//newOrb.transform.localPosition = new Vector3(currentX, currentY, 0);
newOrb.transform.position = orbSpawnPoint.position;
newOrb.GetComponent<RectTransform>().sizeDelta = new Vector2(spriteSize, spriteSize);
Orb newOrbScript = newOrb.GetComponent<Orb>();
newOrbScript.colourManager = GetComponent<ColourManager>();
newOrbScript.FakeStart();
orbSpawnPoint.localPosition = new Vector3(orbSpawnPoint.localPosition.x + orbXSpacing, orbSpawnPoint.localPosition.y, orbSpawnPoint.localPosition.z);
}
orbSpawnPoint.localPosition = new Vector3(startingX, orbSpawnPoint.localPosition.y, orbSpawnPoint.localPosition.z);
orbSpawnPoint.localPosition = new Vector3(orbSpawnPoint.localPosition.x, orbSpawnPoint.localPosition.y + orbYSpacing, orbSpawnPoint.localPosition.z);
//currentY += orbYSpacing;
}
}
private void ResetPositions()
{
orbSpawnPoint.localPosition = new Vector3(startingX, startingY, 0);
}
}
I hope there’s a horizontal scroll to that code because the way it’s thrown half the comments to second lines makes it rather unreadable.
Anyway I’ve tried a good while to fix this and just can’t seem to get it to work. If anyone has any ideas I would appreciate it. My ability to translate between transform.positions and sprite sizes seems to have failed. My maths is probably down there with it though.
Thanks!