How can I add/remove/destroy more or less objects at runtime ?
The script is a bit long I'm not sure what I can reduce I will try.
When I'm running the program it's starting by making the square formation.
What I'm trying to archive is that at each time in runtime if I change the numberOfSquadMembers value up or down add/remove to each squad the more/less value of squad members.
Same for the numberOfSquads value.
The problem is I'm not sure how to do it in the Update() how to add more squads/squad memebers or destroy when the values are less then the current ?
instantiate and destroy is the way the problem is how to maintenance keeping the current formation/s when adding or removing the squads/squads members.
The first script that generate first time the squads and the squads members :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SquadsGenerator : MonoBehaviour
{
public GameObject squadPrefab;
public GameObject squadMemberPrefab;
public int numberOfSquads;
public int numberOfMembersInsquad;
private GameObject squadsParent;
private void Start()
{
squadsParent = GameObject.Find("Squads");
GenerateSquads(numberOfSquads,
numberOfMembersInsquad, squadMemberPrefab, squadPrefab);
}
// Update is called once per frame
void Update()
{
}
public void GenerateSquads(int squadsCount,
int numberOfMembers,
GameObject squadMemberPrefab, GameObject squadPrefab)
{
for (int i = 0; i < squadsCount; i++)
{
var newSquad = Instantiate(squadPrefab);
newSquad.name = "Squad " + i;
newSquad.tag = "Squad";
newSquad.transform.parent = squadsParent.transform;
for (int x = 0; x < numberOfMembers; x++)
{
var go = Instantiate(squadMemberPrefab);
go.name = "Member " + x;
go.tag = "Squad Member";
go.transform.parent = newSquad.transform;
switch (i % 6)
{
case 0: ColorSquad(go, Color.green); break;
case 1: ColorSquad(go, Color.red); break;
case 2: ColorSquad(go, Color.blue); break;
case 3: ColorSquad(go, Color.yellow); break;
case 4: ColorSquad(go, Color.cyan); break;
case 5: ColorSquad(go, Color.magenta); break;
}
}
}
}
private void ColorSquad(GameObject squad, Color color)
{
Renderer rend = squad.GetComponent<Renderer>();
rend.material.SetColor("_Color", color);
}
}
and this script handle the formations with the generated squads and member squads :
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class Formations : MonoBehaviour
{
enum Formation
{
Square, Circle, Triangle
}
[Header("Main Settings")]
[Space(5)]
[Range(4, 100)]
public int numberOfSquadMembers = 20;
[Range(1, 20)]
public int numberOfSquads = 1;
[Range(0, 4)]
public int columns = 4;
public int gaps = 10;
public int circleRadius = 10;
public float yOffset = 0;
[Range(3, 50)]
public float moveSpeed = 3;
[Range(3, 50)]
public float rotateSpeed = 1;
public float threshold = 0.1f;
public bool randomSpeed = false;
[Range(1, 100)]
public int randSpeedMin = 1;
[Range(1, 100)]
public int randSpeedMax = 1;
public bool startRandomFormation = false;
public string currentFormation;
private Formation formation;
private List<Quaternion> quaternions = new List<Quaternion>();
private List<Vector3> newpositions = new List<Vector3>();
private bool move = false;
private bool squareFormation = false;
private List<GameObject> squadMembers = new List<GameObject>();
private float[] step;
private int[] randomSpeeds;
private int index = 0;
private bool ready = false;
private GameObject[] squads;
private Vector3 startVector;
private Vector3 total;
private List<Vector3> endpositions = new List<Vector3>();
public void InitFormations()
{
if (startRandomFormation)
{
formation = (Formation)UnityEngine.Random.Range(0, Enum.GetNames(typeof(Formation)).Length);
}
else
{
formation = Formation.Square;
}
squads = GameObject.FindGameObjectsWithTag("Squad");
for (int i = 0; i < squads.Length; i++)
{
foreach (Transform squadMember in squads[i].transform)
{
squadMembers.Add(squadMember.gameObject);
}
}
foreach (GameObject unit in squadMembers)
{
if (unit != null)
{
total += unit.transform.position;
}
}
Vector3 center = total / squadMembers.Count;
//Vector3 endPos = GameObject.Find("Cube").transform.position;
foreach (GameObject unit in squadMembers)
{
startVector = unit.transform.position - center;
endpositions.Add(/*endPos + */startVector);
}
currentFormation = formation.ToString();
ChangeFormation();
randomSpeeds = RandomSpeeds(randSpeedMin, randSpeedMax, squadMembers.Count);
step = new float[squadMembers.Count];
ready = true;
}
private void Start()
{
InitFormations();
}
// Update is called once per frame
void Update()
{
if (ready == true)
{
if (Input.GetKeyDown(KeyCode.C))
{
randomSpeeds = RandomSpeeds(randSpeedMin, randSpeedMax, squadMembers.Count);
foreach (int speedV in randomSpeeds)
{
if (index == randomSpeeds.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;
case Formation.Triangle:
FormationTriangle();
break;
}
}
private void FormationTriangle()
{
newpositions = new List<Vector3>();
int height = Mathf.CeilToInt((Mathf.Sqrt(8 * squadMembers.Count + 1f) - 1f) / 2);
int slots = (int)(height * (height + 1f) / 2f);
float verticalModifier = 1.25f; // * 1.25f to increase horizontal space
float horizontalModifier = 0.8f; // * 0.8f to decrease "vertical" space
float width = 0.5f * (height - 1f);
Vector3 startPos = new Vector3(width * horizontalModifier, 0f, (float)(height - 1f) * verticalModifier);
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);
}
}
move = true;
formation = Formation.Square;
}
private Vector3 FormationSquarePositionCalculation(int index) // call this func for all your objects
{
float posX = (index % columns) * gaps;
float posY = (index / columns) * gaps;
return new Vector3(posX, posY);
}
private void FormationSquare()
{
newpositions = new List<Vector3>();
quaternions = new List<Quaternion>();
for (int i = 0; i < squadMembers.Count; i++)
{
Vector3 pos = FormationSquarePositionCalculation(i);
//squadMembers[i].transform.position = new Vector3(transform.position.x + pos.x, 0, transform.position.y + pos.y);
squadMembers[i].transform.Rotate(new Vector3(0, -90, 0));
//newpositions.Add(new Vector3(transform.position.x + pos.x, 0, transform.position.y + pos.y));
newpositions.Add(new Vector3(endpositions[i].x + pos.x, 0, endpositions[i].y + pos.y));
}
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()
{
newpositions = new List<Vector3>();
quaternions = new List<Quaternion>();
Vector3 center = transform.position;
float radius = (float)circleRadius / 2;
float angleIncrement = 360 / squadMembers.Count;//(float)numberOfSquadMembers;
for (int i = 0; i < squadMembers.Count; i++)//numberOfSquadMembers; i++)
{
Vector3 pos = FormationCirclePositionCalculation(center, radius, i, angleIncrement);
var rot = Quaternion.LookRotation(center - pos);
if (Terrain.activeTerrain == true)
pos.y = Terrain.activeTerrain.SampleHeight(pos);
pos.y = pos.y + yOffset;
newpositions.Add(pos);
quaternions.Add(rot);
}
move = true;
squareFormation = false;
formation = Formation.Triangle;
}
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);
}
}
}
}
private static int[] RandomSpeeds(int min, int max, int howMany)
{
int[] myNumbers = new int[howMany];
for (int i = 0; i < howMany; i++)
{
myNumbers[i] = UnityEngine.Random.Range(min, max);
}
return myNumbers;
}
}
Answer by unity_hosein · Nov 14, 2021 at 03:49 AM
Use Object.Destroy(GameObject or Component of GameObject);
Your answer
Follow this Question
Related Questions
Enabling & Disabling Script via On Click 1 Answer
Can someone please help me find out what wrong with my code. 0 Answers
The laser problems 0 Answers
How can i make sure the script will work only on the attached object ? 1 Answer
How can I check if a object in the hierarchy have been destroyed using EditorWindow type script ? 1 Answer