private void FormationTriangle()
{
newpositions = new List<Vector3>();
for (int x = 0; x < squadMembers.Count; x++)
{
for (int y = x; y < 2 * (squadMembers.Count - x) - 1; y++)
{
Vector3 position = new Vector3(x, y);
newpositions.Add(position);
}
}
move = true;
formation = Formation.Square;
}
The loops are wrong. It put the squadMembers in one line one above the other. Not even close to a triangle shape. I want the squadMembers to stand in a triangle shape.
This is the moving part: But the problem is with the loops calculating the triangle shape positions. Other formations I did are working fine.
private void MoveToNextFormation()
{
if (randomSpeed == false)
{
if (step.Length > 0)
step[0] = moveSpeed * Time.deltaTime;
}
for (int i = 0; i < squadMembers.Count; i++)
{
squadMembers[i].transform.LookAt(newpositions[i]);
if (randomSpeed == true)
{
squadMembers[i].transform.position = Vector3.MoveTowards(
squadMembers[i].transform.position, newpositions[i], step[i]);
}
else
{
squadMembers[i].transform.position = Vector3.MoveTowards(
squadMembers[i].transform.position, newpositions[i], step[0]);
}
if (Vector3.Distance(squadMembers[i].transform.position, newpositions[i]) <
threshold)
{
if (squareFormation == true)
{
Vector3 degrees = new Vector3(0, 0, 0);
Quaternion quaternion = Quaternion.Euler(degrees);
squadMembers[i].transform.rotation = Quaternion.Slerp(
squadMembers[i].transform.rotation, quaternion,
rotateSpeed * Time.deltaTime);
}
else
{
squadMembers[i].transform.rotation = Quaternion.Slerp(
squadMembers[i].transform.rotation, quaternions[i],
rotateSpeed * Time.deltaTime);
}
}
}
}
x x x x x x x x x x x x x x x
x x x x x x x x x x x x x
Since you aren't guaranteed a perfectly triangular number of units, you should overestimate how big your triangle is, keep count of how many units you have placed, and then quit placing them when you reach your limit.
First, find the height of the smallest triangular number greater than your number of units, and that triangular number itself:
int height = Mathf.CeilToInt( (Mathf.Sqrt(8*squadMembers.Count+1f)-1f)/2 )
int slots = (int)(height * (height+1f)/2f)
Then, find the position of the first unit. We need to know how many rows of slots we have and how wide the bottom row of slots is:
float verticalModifier = 0.8f; // 0.8f to decrease vertical space
float horizontalModifier = 1.25f; // 1.25f to increase horizontal space
float width = 0.5f * (height-1f);
Vector3 startPos = new Vector3(width* horizontalModifier, 0f, (float)(height-1f) * verticalModifier);
Then, add until you've added enough
int finalRowCount = height - slots + squadMembers.Count;
for (int rowNum = 0 ; rowNum < height && newpositions.Count < squadMembers.Count; rowNum++) {
for (int i = 0 ; i < rowNum+1 && newpositions.Count < squadMembers.Count ; i++ ) {
float xOffset = 0f;
if (rowNum+1 == height) {
// If we're in the last row, stretch it ...
if (finalRowCount !=1) {
// Unless there's only one item in the last row.
// If that's the case, leave it centered.
xOffset = Mathf.Lerp(
rowNum/2f,
-rowNum/2f,
i/(finalRowCount-1f)
) * horizontalModifier;
}
}
else {
xOffset = (i-rowNum /2f) * horizontalModifier;
}
float yOffset = (float)rowNum * verticalModifier;
Vector3 position = new Vector3(
startPos.x + xOffset, 0f, startPos.y - yOffset);
newpositions.Add(position);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With