using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SquadFormation : MonoBehaviour
{
enum Formation
{
Square, Circle, Triangle
}
public Transform squadMemeber;
public int columns = 4;
public int squareSpace = 10;
public int circleSpace = 40;
public int numberOfObjects = 20;
public float yOffset = 0;
[Range(3,50)]
public float moveSpeed = 3;
public bool randomSpeed = false;
public float rotateSpeed = 1;
public float threshold = 0.1f;
public bool destroySquad = false;
private Formation formation;
private List<Quaternion> qua = new List<Quaternion>();
private List<Vector3> newpos = new List<Vector3>();
private bool move = false;
private bool squareFormation = false;
private List<GameObject> squadMembers = new List<GameObject>();
private int[] randomSpeeds = new int[30];
// Use this for initialization
void Start()
{
CreateRandomSpeedArray();
formation = Formation.Square;
ChangeFormation();
foreach (Transform child in gameObject.transform)
{
if (child.tag == "Squad Member")
squadMembers.Add(child.gameObject);
}
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.F))
{
if (destroySquad == true)
{
GameObject[] objects = GameObject.FindGameObjectsWithTag("Squad Member");
if (objects.Length > 0)
{
foreach (GameObject obj in objects)
Destroy(obj);
}
}
ChangeFormation();
}
if (move == true)
MoveToNextFormation();
}
private void ChangeFormation()
{
switch (formation)
{
case Formation.Square:
FormationSquare();
break;
case Formation.Circle:
FormationCircle();
break;
}
}
private Vector3 FormationSquarePositionCalculation(int index) // call this func for all your objects
{
float posX = (index % columns) * squareSpace;
float posY = (index / columns) * squareSpace;
return new Vector3(posX, posY);
}
private void FormationSquare()
{
newpos = new List<Vector3>();
qua = new List<Quaternion>();
Transform go = squadMemeber;
for (int i = 0; i < numberOfObjects; i++)
{
if (squadMembers.Count == 0)
go = Instantiate(squadMemeber);
Vector3 pos = FormationSquarePositionCalculation(i);
go.position = new Vector3(transform.position.x + pos.x, 0, transform.position.y + pos.y);
go.Rotate(new Vector3(0, -90, 0));
go.tag = "Squad Member";
go.transform.parent = gameObject.transform;
newpos.Add(go.transform.position);
}
//}
move = true;
squareFormation = true;
formation = Formation.Circle;
}
private Vector3 FormationCirclePositionCalculation(Vector3 center, float radius, int index, float angleIncrement)
{
float ang = index * angleIncrement;
Vector3 pos;
pos.x = center.x + radius * Mathf.Sin(ang * Mathf.Deg2Rad);
pos.z = center.z + radius * Mathf.Cos(ang * Mathf.Deg2Rad);
pos.y = center.y;
return pos;
}
private void FormationCircle()
{
newpos = new List<Vector3>();
qua = new List<Quaternion>();
Vector3 center = transform.position;
float radius = (float)circleSpace / 2;
float angleIncrement = 360 / (float)numberOfObjects;
for (int i = 0; i < numberOfObjects; i++)
{
Vector3 pos = FormationCirclePositionCalculation(center, radius, i, angleIncrement);
var rot = Quaternion.LookRotation(center - pos);
pos.y = Terrain.activeTerrain.SampleHeight(pos);
pos.y = pos.y + yOffset;
newpos.Add(pos);
qua.Add(rot);
}
move = true;
squareFormation = false;
formation = Formation.Square;
}
private void MoveToNextFormation()
{
CreateRandomSpeedArray();
float step = moveSpeed * Time.deltaTime;
for (int i = 0; i < squadMembers.Count; i++)
{
squadMembers[i].transform.LookAt(newpos[i]);
if (randomSpeed == true)
{
squadMembers[i].transform.position =
Vector3.MoveTowards(squadMembers[i].transform.position, newpos[i], randomSpeeds[i] * Time.deltaTime);
}
else
{
squadMembers[i].transform.position =
Vector3.MoveTowards(squadMembers[i].transform.position, newpos[i], step);
}
if (Vector3.Distance(squadMembers[i].transform.position, newpos[i]) < threshold)
{
if (squareFormation == true)
{
Vector3 degrees = new Vector3(0, -90f, 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, qua[i], rotateSpeed * Time.deltaTime);
}
}
}
}
private void CreateRandomSpeedArray()
{
for (int arrayIndex = 0; arrayIndex < randomSpeeds.Length; arrayIndex++)
{
randomSpeeds[arrayIndex] = Random.Range(0, 30);
}
}
}
I have some problems.
First i create array of random numbers each number is a movement speed value. But in the array there are some numbers that are the same some numbers are 0. I want that there will be no same numbers in the array no 0.
Another problem is when i'm using the speed values in the method MoveToNextFormation on the line:
squadMembers[i].transform.position =
Vector3.MoveTowards(squadMembers[i].transform.position, newpos[i], randomSpeeds[i] * Time.deltaTime);
I don't see the characters are moving in random speed they are all moving the same speed and slow. I want each character to move in another speed.
Another problem is in the Update in this part:
if (move == true)
MoveToNextFormation();
I need to call MoveToNextFormation from inside the Update to make the characters move but then move variable will be all the time true and it will keep calling the method MoveToNextFormation over and over again. How can i make that each time the characters finished moving and rotating to stop calling MoveToNextFormation until the next time ? Making move = false; in the bottom of MoveToNextFormation is not working.
I can't even debug the MoveToNextFormation since it's being called every frame in the Update even if the characters are not moving. I want it to be called only when i click on F the problem is that then it will be called once and the character won't move.