1
\$\begingroup\$

I need to know that they are all finished move to the new position.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
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;
    public string currentFormation;

    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];
    private float[] step;
    private int[] speeds;
    private int index = 0;

    // Use this for initialization
    void Start()
    {
        formation = Formation.Square;
        currentFormation = formation.ToString();
        ChangeFormation();

        foreach (Transform child in gameObject.transform)
        {
            if (child.tag == "Squad Member")
                squadMembers.Add(child.gameObject);
        }

        speeds = uniqueRandomNumbers(1, 30, squadMembers.Count);
        step = new float[squadMembers.Count];
    }

    // 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);
                }
            }

            speeds = uniqueRandomNumbers(1, 30, squadMembers.Count);
            foreach (int speedV in speeds)
            {
                if (index == speeds.Length)
                    index = 0;

                step[index] = speedV * Time.deltaTime;
                index++;
            }

            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()
    {
        if (randomSpeed == false)
        {
            step[0] = 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], step[i]);
            }
            else
            {
                squadMembers[i].transform.position =
                Vector3.MoveTowards(squadMembers[i].transform.position, newpos[i], step[0]);
            }
            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 static int[] uniqueRandomNumbers(int min, int max, int howMany)
    {
        // check for impossible combinations
        if (howMany > max - min)
            throw new ArgumentException(String.Format("Range {0}-{1} is too small to have {2} unique random numbers.", min, max, howMany));

        int[] myNumbers = new int[howMany];

        // special case for range and howMany being equal
        if (howMany == max - min)
        {
            // Linq version
            // return Enumerable.Range(min, howMany).ToArray();

            // for loop version
            for (int i = 0; i < howMany; i++)
                myNumbers[i] = i;
            return myNumbers;
        }

        // actual generation of random numbers
        System.Random randNum = new System.Random();
        for (int currIndex = 0; currIndex < howMany; currIndex++)
        {
            // generate a candidate
            int randCandidate = randNum.Next(min, max);

            // generate a new candidate as long as we don't get one that isn't in the array
            while (myNumbers.Contains(randCandidate))
            {
                randCandidate = randNum.Next(min, max);
            }

            myNumbers[currIndex] = randCandidate;
        }

        return myNumbers;
    }
}

I need to check in the MoveToNextFormation method or maybe in the Update when all the squadMembers reached to the new position(newpos) and finished rotating.

I have the public variable: currentFormation

public string currentFormation;

In the Start i set it to the current starting formation so i know it's square. But now i want to set the currentFormation inside the Update or inside the MoveToNextFormation and only when all the objects(squadMembers) reached to the new position(newpos) and finished rotating then to set currentFormation with the current formation name for example in the Start it's Square when i click F the objects will move to Circle formation once they are in Circle formation update currentFormation variable.

\$\endgroup\$
  • 1
    \$\begingroup\$ Just an advice - don't wait for units before changing the formation, let them move into that formation right after you click F, the game will look much smoother and a player will have more control. But I don't know about the type of the game you are creating if you could provide a little description about gameplay that would be useful information to help to answer your question. \$\endgroup\$ – Candid Moon _Max_ Sep 10 '17 at 10:34
  • 2
    \$\begingroup\$ You've posted a very large amount of code. The longer your code snippet, the less people will be willing to invest the time to read it. You might get more and better answers if you reduce your code to a Short, Self Contained, Correct, Example \$\endgroup\$ – Philipp Sep 10 '17 at 10:36
  • \$\begingroup\$ @Philipp I think better to leave the code, but add a short section for people who don't want to spend much time. \$\endgroup\$ – Candid Moon _Max_ Sep 10 '17 at 10:43
  • \$\begingroup\$ @Dragon Flea Your formations are also kind of under the question. Why did you decide just to use other squad member positions to find the right position for your other member? The positions would be inaccurate. You should use Vectors to designate the position of your squad member in the formation grid. The grid can be created without arrays to store some memory. For example, every squad member on addition to the formation is assigned vector2 place (which is a virtual place just to calculate the real position). Then you have a distance between members and middle point. Just calculate the pos. \$\endgroup\$ – Candid Moon _Max_ Sep 10 '17 at 10:48
  • \$\begingroup\$ @CandidMoon Sound logic. Can you please show me some example how to do it ? \$\endgroup\$ – Dragon Flea Sep 10 '17 at 10:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.