How can I add remove more number of objects at runtime? - c#

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/squadmemebers or destroy when the values are less then the current ?
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;
}
}
This is the script that generate the squads and number of squads members first time :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SquadsGenerator : MonoBehaviour
{
public GameObject squadPrefab;
public int numberOfSquads;
public int numberOfMembersInsquad;
private GameObject squadsParent;
private void Start()
{
squadsParent = GameObject.Find("Squads");
GenerateSquads(numberOfSquads, numberOfMembersInsquad, squadPrefab);
}
// Update is called once per frame
void Update()
{
}
public void GenerateSquads(int squadsCount,
int numberOfMembers,
GameObject squadMemberPrefab)
{
for (int i = 0; i < squadsCount; i++)
{
GameObject newSquad = new GameObject();
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);
}
}
Update :
What I have tried so far :
I added this part to the Update()
if(oldNumOfSquadMemebers != numberOfSquadMembers)
{
var tt = numberOfSquadMembers - oldNumOfSquadMemebers;
for (int i = 0; i < tt; i++)
{
var go = Instantiate(squadMemberPrefab);
squadMembers.Add(go);
}
oldNumOfSquadMemebers = numberOfSquadMembers;
FormationSquare();
}
The problem now is in the FormationSquare method :
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.Rotate(new Vector3(0, -90, 0));
newpositions.Add(new Vector3(endpositions[i].x + pos.x, 0, endpositions[i].y + pos.y));
}
move = true;
squareFormation = true;
formation = Formation.Circle;
}
Now I'm making a new instance for the newpositions List so each time I change the number of squad members there are more members but less newpositions so at some time I'm getting out of index exception.
If I don't make a new instance for the List then it will work but then after some time it will throw the out of index exception this time because it keep adding more and more new positions to the list.
So this newpositions List I'm stuck with it. Not sure how to solve it.

Related

Why linerenderer is not changing colors at runetime?

The first script is attached to some object for example a cube and draw a circle around the cube :
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[ExecuteAlways]
[RequireComponent(typeof(UnityEngine.LineRenderer))]
public class DrawCircle : MonoBehaviour
{
[Range(1, 50)] public int segments = 50;
[Range(1, 500)] public float xRadius = 5;
[Range(1, 500)] public float yRadius = 5;
[Range(0.1f, 5)] public float width = 0.1f;
[Range(0, 100)] public float height = 0;
public bool controlBothXradiusYradius = false;
public bool draw = true;
[SerializeField] private LayerMask targetLayers;
[SerializeField] private LineRenderer line;
private void Start()
{
if (!line) line = GetComponent<LineRenderer>();
if (draw)
CreatePoints();
}
private void Update()
{
if (Physics.CheckSphere(transform.position, xRadius, targetLayers))
{
Debug.Log("player detected");
}
else
{
Debug.Log("player NOT detected");
}
}
public void CreatePoints()
{
line.enabled = true;
line.widthMultiplier = width;
line.useWorldSpace = false;
line.widthMultiplier = width;
line.positionCount = segments + 1;
float x;
float y;
var angle = 20f;
var points = new Vector3[segments + 1];
for (int i = 0; i < segments + 1; i++)
{
x = Mathf.Sin(Mathf.Deg2Rad * angle) * xRadius;
y = Mathf.Cos(Mathf.Deg2Rad * angle) * yRadius;
points[i] = new Vector3(x, height, y);
angle += (380f / segments);
}
// it's way more efficient to do this in one go!
line.SetPositions(points);
}
#if UNITY_EDITOR
private float prevXRadius, prevYRadius;
private int prevSegments;
private float prevWidth;
private float prevHeight;
private void OnValidate()
{
// Can't set up our line if the user hasn't connected it yet.
if (!line) line = GetComponent<LineRenderer>();
if (!line) return;
if (!draw)
{
// instead simply disable the component
line.enabled = false;
}
else
{
// Otherwise re-enable the component
// This will simply re-use the previously created points
line.enabled = true;
if (xRadius != prevXRadius || yRadius != prevYRadius || segments != prevSegments || width != prevWidth || height != prevHeight)
{
CreatePoints();
// Cache our most recently used values.
prevXRadius = xRadius;
prevYRadius = yRadius;
prevSegments = segments;
prevWidth = width;
prevHeight = height;
}
if (controlBothXradiusYradius)
{
yRadius = xRadius;
CreatePoints();
}
}
}
#endif
}
The result is a drawn circle around the cube with the default color in pink :
The second script is also attached to the same cube with the drawn circle and animate colors to be rotating on the linerenderer circle :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(LineRenderer))]
public class LineRendererColors : MonoBehaviour
{
public enum AnimationType { None, SingleColorMorph, MultiColorMorph, Shuffle, Shift };
public AnimationType myAnimationType;
LineRenderer myLineRenderer;
public float morphTime = 2;
void Start()
{
myLineRenderer = this.GetComponent<LineRenderer>();
switch (myAnimationType)
{
case AnimationType.SingleColorMorph:
StartCoroutine(RandomSingleColorMorphing(myLineRenderer, morphTime));
break;
case AnimationType.MultiColorMorph:
StartCoroutine(RandomMultiColorMorphing(myLineRenderer, morphTime));
break;
case AnimationType.Shuffle:
StartCoroutine(ShuffleGradient(myLineRenderer, .5f));
break;
case AnimationType.Shift:
StartCoroutine(AnimateLoop(myLineRenderer));
break;
}
}
void SetSingleColor(LineRenderer lineRendererToChange, Color newColor)
{
lineRendererToChange.startColor = newColor;
lineRendererToChange.endColor = newColor;
}
void SetSingleColor2(LineRenderer lineRendererToChange, Color newColor)
{
Gradient tempGradient = new Gradient();
GradientColorKey[] tempColorKeys = new GradientColorKey[2];
tempColorKeys[0] = new GradientColorKey(newColor, 0);
tempColorKeys[1] = new GradientColorKey(newColor, 1);
tempGradient.colorKeys = tempColorKeys;
lineRendererToChange.colorGradient = tempGradient;
}
void SetSingleColor3(LineRenderer lineRendererToChange, Color newColor)
{
Gradient tempGradient = lineRendererToChange.colorGradient;
GradientColorKey[] tempColorKeys = tempGradient.colorKeys;
for (int i = 0; i < tempColorKeys.Length; i++)
{
tempColorKeys[i].color = newColor;
}
tempGradient.colorKeys = tempColorKeys;
lineRendererToChange.colorGradient = tempGradient;
}
IEnumerator ShuffleGradient(LineRenderer targetLineRenderer, float waitTime)
{
while (true)
{
ShuffleGradient(targetLineRenderer);
yield return new WaitForSeconds(waitTime);
}
}
void ShuffleGradient(LineRenderer targetLineRenderer)
{
GradientColorKey[] newColorKeys = targetLineRenderer.colorGradient.colorKeys;
for (int i = 0; i < newColorKeys.Length; i++)
{
Color tempColor = newColorKeys[i].color;
int randomIndex = Random.Range(0, newColorKeys.Length - 1);
newColorKeys[i].color = newColorKeys[randomIndex].color;
newColorKeys[randomIndex].color = tempColor;
}
Gradient tempGradient = targetLineRenderer.colorGradient;
tempGradient.colorKeys = newColorKeys;
targetLineRenderer.colorGradient = tempGradient;
}
IEnumerator RandomMultiColorMorphing(LineRenderer lineRendererToChange, float timeToMorph)
{
float time = 0;
while (true)
{
GradientColorKey[] initialColorKeys = lineRendererToChange.colorGradient.colorKeys;
GradientColorKey[] newColorKeys = GenerateRandomColorKeys(initialColorKeys);
time = 0;
while (time < timeToMorph)
{
time += Time.deltaTime;
float progress = time / timeToMorph;
GradientColorKey[] currentColorKeys = GradientColorKeyLerp(initialColorKeys, newColorKeys, progress);
Gradient tempGradient = lineRendererToChange.colorGradient;
tempGradient.colorKeys = currentColorKeys;
lineRendererToChange.colorGradient = tempGradient;
yield return null;
}
yield return null;
}
}
GradientColorKey[] GradientColorKeyLerp(GradientColorKey[] initialColorKeys, GradientColorKey[] endColorKeys, float progress)
{
GradientColorKey[] newColorKeys = new GradientColorKey[initialColorKeys.Length];
for (int i = 0; i < newColorKeys.Length; i++)
{
newColorKeys[i].color = Color.Lerp(initialColorKeys[i].color, endColorKeys[i].color, progress);
newColorKeys[i].time = initialColorKeys[i].time;
}
return newColorKeys;
}
//assigns new color to each colorkey and uses Time from incomingColorKeys
GradientColorKey[] GenerateRandomColorKeys(GradientColorKey[] incomingColorKeys)
{
GradientColorKey[] newColorKeys = new GradientColorKey[incomingColorKeys.Length];
for (int i = 0; i < newColorKeys.Length; i++)
{
newColorKeys[i].color = RandomColor();
newColorKeys[i].time = incomingColorKeys[i].time;
}
return newColorKeys;
}
//asumes Single color, 2 colorkeys
IEnumerator RandomSingleColorMorphing(LineRenderer lineRendererToChange, float timeToMorph)
{
float time = 0;
Color initialColor = lineRendererToChange.colorGradient.colorKeys[0].color;
//this reduces colorkey amount to 2 just in case.
SetSingleColor2(lineRendererToChange, initialColor);
while (true)
{
initialColor = lineRendererToChange.colorGradient.colorKeys[0].color;
Color targetColor = RandomColor();
time = 0;
while (time < timeToMorph)
{
time += Time.deltaTime;
float progress = time / timeToMorph;
Color currentColor = Color.Lerp(initialColor, targetColor, progress);
SetSingleColor(lineRendererToChange, currentColor);
yield return null;
}
yield return null;
}
}
//Basically Color.Lerp?
Color ColorLerpMath(Color firstColor, Color secondColor, float progress)
{
Vector3 firstRGB = new Vector3(firstColor.r, firstColor.g, firstColor.b);
Vector3 secondRGB = new Vector3(secondColor.r, secondColor.g, secondColor.b);
Vector3 difference = secondRGB - firstRGB;
Vector3 lerpedRGB = firstRGB + (progress * difference);
return new Color(lerpedRGB.x, lerpedRGB.y, lerpedRGB.z);
}
Color RandomColor()
{
return new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f));
}
//returns the gradient with a copy of the first key for intersection purposes.
Gradient AddInitialCopy(Gradient incomingGradient)
{
List<GradientColorKey> newColorKeys = new List<GradientColorKey>(incomingGradient.colorKeys);
Color interSectionColor = newColorKeys[0].color;
newColorKeys.Insert(0, new GradientColorKey(interSectionColor, 0));
Gradient newInitGradient = new Gradient();
newInitGradient.colorKeys = newColorKeys.ToArray();
return newInitGradient;
}
//remove first and last keys since they dont shift.
List<GradientColorKey> RemoveFirstAndLast(Gradient incomingGradient)
{
List<GradientColorKey> currentColorKeys = new List<GradientColorKey>(incomingGradient.colorKeys);
currentColorKeys.RemoveAt(currentColorKeys.Count - 1);
currentColorKeys.RemoveAt(0);
return currentColorKeys;
}
Color GetIntersectionColor(List<GradientColorKey> incomingKeys, int lowestIndex, int highestIndex)
{
Color firstColor = incomingKeys[lowestIndex].color;
Color lastColor = incomingKeys[highestIndex].color;
float distance = 1 - (incomingKeys[highestIndex].time - incomingKeys[lowestIndex].time);
float colorLerpAmount = (1f - incomingKeys[highestIndex].time) / distance; ;
Color newIntersectionColor = Color.Lerp(lastColor, firstColor, colorLerpAmount);
return newIntersectionColor;
}
//accepts max 7 colors, 1st and last should be at 0 and 1
IEnumerator AnimateLoop(LineRenderer lineRendererToChange, float movementPerTick = .001f)
{
lineRendererToChange.colorGradient = AddInitialCopy(lineRendererToChange.colorGradient);
while (true)
{
List<GradientColorKey> currentColorKeys = RemoveFirstAndLast(lineRendererToChange.colorGradient);
float highestTime = 0;
float lowestTime = 1;
int highestIndex = currentColorKeys.Count - 1;
int lowestIndex = 0;
//Move all inner ones.
for (int i = 0; i < currentColorKeys.Count; i++)
{
GradientColorKey tempColorKey = currentColorKeys[i];
float newTime = tempColorKey.time + movementPerTick;
if (newTime > 1)
{
newTime = newTime - 1;
}
tempColorKey.time = newTime;
currentColorKeys[i] = tempColorKey;
if (newTime < lowestTime)
{
lowestTime = newTime;
lowestIndex = i;
}
if (newTime > highestTime)
{
highestTime = newTime;
highestIndex = i;
}
}
Color newIntersectionColor = GetIntersectionColor(currentColorKeys, lowestIndex, highestIndex);
currentColorKeys.Insert(0, new GradientColorKey(newIntersectionColor, 0));
currentColorKeys.Add(new GradientColorKey(newIntersectionColor, 1));
Gradient tempGradient = lineRendererToChange.colorGradient;
tempGradient.colorKeys = currentColorKeys.ToArray();
lineRendererToChange.colorGradient = tempGradient;
yield return null;
}
}
void AssignGradient(LineRenderer targetLineRenderer, Gradient newGradient)
{
targetLineRenderer.colorGradient = newGradient;
}
void DrawTestLine()
{
Vector3 firstPos = new Vector3(-5, 0, 0);
Vector3 secondPos = new Vector3(5, 0, 0);
int resolution = 100;
myLineRenderer.positionCount = resolution;
myLineRenderer.SetPositions(MakeLine(firstPos, secondPos, 100));
}
//makes a line from point A to point B with resolution of size points
Vector3[] MakeLine(Vector3 initPos, Vector3 endPos, int points)
{
Vector3 difference = endPos - initPos;
Vector3[] newLine = new Vector3[points];
Vector3 differencePerPoint = difference / (float)(points - 1);
for (int i = 0; i < points; i++)
{
newLine[i] = initPos + (differencePerPoint * i);
}
return newLine;
}
}
When i'm running the game i see in the editor that the Color property of the linerenderer is changing in animation but the circle it self stay in the same default pink color and never change :
This is because the line renderer has no material. Add the appropriate material to your line renderer to solve the problem. If you want to add material through the code, you can do the following, but Unity usually makes changes to the shaders in each version, which may make it difficult to find the name of the shader.
if (!lineRenderer.material)
lineRenderer.material = new Material(Shader.Find("Sprites/Default"));

Drawing a Mandelbrot Set

I'm trying to make the function of the Mandelbrot Set, and I'm not sure what I'm doing wrong or right, here's the code:
private void StartCircles()
{
float savePower = BlackCircle.anchoredPosition.x;
GameObject[] AllCircles = new GameObject[itarations];
AllCircles[0] = BlackCircle.gameObject;
for (int i = 1; i < itarations; i++)
{
GameObject Circle = Instantiate(BlackCircle.gameObject, Vector3.zero, Quaternion.identity);
Circle.transform.SetParent(CanvasPerent);
savePower = Mathf.Pow(savePower, 2);
savePower += RedCircle.anchoredPosition.x;
Circle.GetComponent<RectTransform>().anchoredPosition = new Vector2(savePower,
AllCircles[i - 1].GetComponent<RectTransform>().anchoredPosition.y * -1);
AllCircles[i] = Circle;
}
CleanSqud = new GameObject[itarations];
CleanSqud = AllCircles;
}
I'm not sure what the y position should be and how could the x position be < 0 if it's a power of 2, it's automaticly > 0.
Here's the display:
i manged to get my code working after some time and i got some answars to share if anyone has my problen:
well i only wanted to make the function of the zn + 1 = zn * zn + c
i dident made the full set only this function, heres my code:
#region Actions
private void OnDestroy()
{
MoveBlack.HasMoved -= HasMoved;
MoveBlack.HasStoped -= HasStoped;
MoveRed.HasMoved -= HasMoved;
MoveRed.HasStoped -= HasStoped;
}
private void LateUpdate()
{
if (moved) { updateCircles(); }
if (hasparty)
{
foreach(GameObject game in CleanSqud)
{
game.GetComponent<Image>().color = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f));
}
}
}
private void HasMoved()
{
moved = true;
}
private void HasStoped()
{
moved = false;
}
#endregion
#region Updateing
private void updateCircles()
{
foreach (GameObject Circle in CleanSqud) { if (Circle.gameObject.name != "BlackCirlce") { Destroy(Circle); } }
StartCircles();
}
private void StartCircles()
{
float x = BlackCircle.anchoredPosition.x;
float y = BlackCircle.anchoredPosition.y;
GameObject[] AllCircles = new GameObject[itarations];
AllCircles[0] = BlackCircle.gameObject;
for (int i = 1; i < itarations; i++)
{
GameObject Circle = Instantiate(BlackCircle.gameObject, Vector3.zero, Quaternion.identity);
Circle.transform.SetParent(CanvasPerent);
AllCircles[i] = Circle;
x = Mathf.Pow(x, 2);
x -= Mathf.Pow(AllCircles[i - 1].GetComponent<RectTransform>().anchoredPosition.y, 2);
x += RedCircle.anchoredPosition.x;
y = (2 * AllCircles[i - 1].GetComponent<RectTransform>().anchoredPosition.x
* AllCircles[i - 1].GetComponent<RectTransform>().anchoredPosition.y) + RedCircle.anchoredPosition.y;
Circle.GetComponent<RectTransform>().anchoredPosition = new Vector2(x, y);
}
CleanSqud = new GameObject[itarations];
CleanSqud = AllCircles;
}
#endregion
so what you should do is instad of showing the y as a imaginary and the x as real show it using the equastion:
this x = power of the old x - power of the old y + c.x
this y = 2 * the old x * the old y + c.y
this should work!
thanks.

How can I add more lights if twoSides flag is true?

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LightsEffect : MonoBehaviour
{
public List<UnityEngine.GameObject> waypoints;
public int howmanylight = 5;
public bool changeLightsDirection = false;
public bool twoSides = false;
public float delay = 0.1f;
private List<UnityEngine.GameObject> objects;
private Renderer[] renderers;
private int greenIndex = 0;
private float lastChangeTime;
private void Start()
{
objects = new List<UnityEngine.GameObject>();
if (howmanylight > 0)
{
UnityEngine.GameObject go1 = UnityEngine.GameObject.CreatePrimitive(PrimitiveType.Sphere);
duplicateObject(go1, howmanylight);
LightsEffects();
}
}
private void Update()
{
LightsEffectCore();
}
public void duplicateObject(UnityEngine.GameObject original, int howmany)
{
if (twoSides == true)
howmany = howmany * 2;
howmany++;
for (int i = 0; i < waypoints.Count - 1; i++)
{
for (int j = 1; j < howmany; j++)
{
Vector3 position = waypoints[i].transform.position + j * (waypoints[i + 1].transform.position - waypoints[i].transform.position) / howmany;
UnityEngine.GameObject go = Instantiate(original, new Vector3(position.x, 0.05f, position.z), Quaternion.identity);
go.transform.localScale = new Vector3(0.3f, 0.1f, 0.3f);
objects.Add(go);
}
}
}
private void LightsEffects()
{
renderers = new Renderer[objects.Count];
for (int i = 0; i < renderers.Length; i++)
{
renderers[i] = objects[i].GetComponent<Renderer>();
renderers[i].material.color = Color.red;
}
// Set green color to the first one
greenIndex = 0;
renderers[greenIndex].material.color = Color.green;
}
private void LightsEffectCore()
{
// Change color each `delay` seconds
if (Time.time > lastChangeTime + delay)
{
lastChangeTime = Time.time;
// Set color of the last renderer to red
// and the color of the current one to green
renderers[greenIndex].material.color = Color.red;
if (changeLightsDirection == true)
{
Array.Reverse(renderers);
changeLightsDirection = false;
}
greenIndex = (greenIndex + 1) % renderers.Length;
renderers[greenIndex].material.color = Color.green;
}
}
}
Inside the method duplicateObject I'm checking if the flag twoSides is true and then double by twice the amount of lights:
public void duplicateObject(UnityEngine.GameObject original, int howmany)
{
if (twoSides == true)
howmany = howmany * 2;
howmany++;
for (int i = 0; i < waypoints.Count - 1; i++)
{
for (int j = 1; j < howmany; j++)
{
Vector3 position = waypoints[i].transform.position + j * (waypoints[i + 1].transform.position - waypoints[i].transform.position) / howmany;
UnityEngine.GameObject go = Instantiate(original, new Vector3(position.x, 0.05f, position.z), Quaternion.identity);
go.transform.localScale = new Vector3(0.3f, 0.1f, 0.3f);
objects.Add(go);
}
}
}
This lines:
if (twoSides == true)
howmany = howmany * 2;
But this will add just more 5 lights between the waypoints like it show in the screenshot.
And I want it to add more 5 lights but to create two lines between the waypoints of lights line by line.
Somehow to change the new 5 lights position so it will be near/next the first 5 lights. And then to align the lines of lights so they will be equal between the waypoints.
Two lines and two sides I mean something like this:
But they should be equal between the waypoints like in the first screenshot.
What I tried is this:
Changed the duplicateObject method to:
public void duplicateObject(UnityEngine.GameObject original, int howmany)
{
GameObject go = new GameObject();
if (twoSides == true)
howmany = howmany * 2;
howmany++;
for (int i = 0; i < waypoints.Count - 1; i++)
{
for (int j = 1; j < howmany; j++)
{
Vector3 position = waypoints[i].transform.position + j * (waypoints[i + 1].transform.position - waypoints[i].transform.position) / howmany;
if (j > 5)
{
go = Instantiate(original, new Vector3(position.x + 1, 0.05f, position.z), Quaternion.identity);
}
else
{
go = Instantiate(original, new Vector3(position.x, 0.05f, position.z), Quaternion.identity);
}
go.transform.localScale = new Vector3(0.3f, 0.1f, 0.3f);
objects.Add(go);
}
}
}
But the result is not what I wanted:
Now the problem is that the lights the gaps between them is not equal between the two waypoints (cubes) and also the new 5 lights are two far from the waypoints.
Both lights each 5 lights should be with equal gaps and side by side between the waypoints. Like a landing lights for aircraft between the two waypoints.

Unity RTS Total War Style Click and Drag Unit Formation

I've been working in unity trying to implement the total war style of unit formation width/depth creation with click and drag like seen in this video at about 15 seconds:
https://www.youtube.com/watch?v=3aGRzy_PzJQ
I have written some code, but I am getting out of index errors. Here it is so far:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Formation : MonoBehaviour {
// Use this for initialization
void Start()
{
formationMaker();
}
private void FixedUpdate()
{
formationShape();
}
public GameObject unit;//this is a cube prefab with scale dimensions .45,1.8,.3
public Transform parent;//this is the parent object of the cubes acting as anchor point
private Vector3 startClick;
private Vector3 endClick;
private float width;
private List<GameObject> unitsList = new List<GameObject>();
private int numberOfMen;
private int rows;
private int leftOverMen;//was going to use these two to calculate the number of men in the last row and...
private int lastRowSpace;//...the amount of space needed to center them
private int count;
private float manWidth = (float)4.5;
private void formationMaker()//this makes the formation upon start
{
for(int x = -10; x< 10; x++)
{
for(int z = -4; z< 4; z++)
{
Instantiate(unit, new Vector3(x* .7F, .9f, z*1.0f), Quaternion.identity, parent);
unitsList.Add(unit);
}
}
}
private void formationShape()
{
if (Input.GetMouseButtonDown(1))
{
startClick = Input.mousePosition;
}
else if (Input.GetMouseButtonUp(1))
{
endClick = Input.mousePosition;
}
//ERROR HERE?
width = Vector3.Distance(startClick, endClick)/manWidth;//width has to be the width in terms of number of men, but i'm not sure where to get this width
//ERROR HERE
numberOfMen = unitsList.Count;
rows = (int)Mathf.Floor(numberOfMen / width);
leftOverMen = (int)Mathf.Ceil(numberOfMen % width);
lastRowSpace = ((int)width - leftOverMen) / 2;
Debug.Log(rows);
Debug.Log(width);
Debug.Log(numberOfMen);
if (width != 0)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < width; j++)
{
unitsList[count].transform.position = new Vector3(i * .7F, .9f, j * 1.0f) + startClick;
count++;
}
}
}
width = 0;
}
void Update () {
}
}
Thanks for any help!
Your count not reset to zero,and you should convert width to int to eliminate the error.
PS.Input.mousePosition is pixel coordinates,not world position!
You can't get world position by use Input.mousePosition ( use Raycast instead)
Your width can be zero => (int)Mathf.Floor(numberOfMen / width); can lead to errors
If you still look for solution, you can refer to this code (I edited from your code)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Formation : MonoBehaviour
{
public int numberSpawn;
// Use this for initialization
private void Awake()
{
m_BoxSelected = new BoxSelected();
}
void Start()
{
//count = 0;
//formationMaker();
formationMaker(new Vector3(1, 1, 1), new Vector3(1, 1, 1), 30, numberSpawn);
//formationMaker3(new Vector3(), new Vector3(-20, 0, -20), 2f, ref unitsList);
}
private void FixedUpdate()
{
}
public BoxSelected m_BoxSelected;
public Camera m_MainCamera;
private Ray m_ray;
public GameObject unit;//this is a cube prefab with scale dimensions .45,1.8,.3
public Transform parent;//this is the parent object of the cubes acting as anchor point
private Vector3 startClick;
private Vector3 endClick;
private float width;
[SerializeField]
private List<GameObject> unitsList = new List<GameObject>();
private int numberOfMen;
[SerializeField]
private float manWidth = (float)4.5;
private void formationMaker()//this makes the formation upon start
{
for (int x = 0; x < 4; x++)
{
for (int z = 0; z < 4; z++)
{
Instantiate(unit, new Vector3(x * .7F, 0f, z * 1.0f), Quaternion.identity, parent);
unitsList.Add(unit);
}
}
}
private void formationMaker(Vector3 _StartPos, Vector3 _EndPos, float SizeObj, int _NumberObj)//this makes the formation upon start
{
float _width = Mathf.Abs(_StartPos.x - _EndPos.x);
float _height = Mathf.Abs(_StartPos.z - _EndPos.z);
int row = 0, col = 0;
if (_width > SizeObj && _height > SizeObj)
{
float dt = _width * _height;
float _SumCanContain = dt / SizeObj;
if (_SumCanContain >= _NumberObj)
{
// OK
}
else
{
// kiểm tra xem mảng có đựng vừa số Obj không
float Temp = Mathf.Sqrt(_NumberObj);
if ((int)(Temp + 0.5) != (int)Temp) // Phần thập phân lớn hơn 0.5
{
row = (int)(Temp + 1);
col = (int)(Temp + 1);
_width = (int)(Temp + 1) * SizeObj;
_height = (int)(Temp + 1) * SizeObj;
}
else
{
row = ((int)(Temp) + 1);
col = (int)(Temp);
_width = ((int)(Temp) + 1) * SizeObj;
_height = (int)(Temp) * SizeObj;
}
}
}
else
{
// kiểm tra xem mảng có đựng vừa số Obj không
float Temp = Mathf.Sqrt(_NumberObj);
if ((int)(Temp + 0.5) != (int)Temp) // Phần thập phân lớn hơn 0.5
{
row = (int)(Temp + 1);
col = (int)(Temp + 1);
_width = (int)(Temp + 1);
_height = (int)(Temp + 1);
}
else
{
row = ((int)(Temp) + 1);
col = (int)(Temp);
_width = ((int)(Temp) + 1);
_height = (int)(Temp);
}
}
int cout = 0;
for (int x = 0; x < _width; x++)
{
for (int z = 0; z < _height; z++)
{
if (cout < _NumberObj)
{
//Instantiate(unit, new Vector3(x * .7F, .9f, z * 1.0f), Quaternion.identity, parent);
unitsList.Add(Instantiate(unit, new Vector3(x * .7F, .9f, z * 1.0f), Quaternion.identity, parent));
cout++;
}
}
}
}
#region Add Funtion
public int ReverseToOne(int value)
{
if (value > 0)
{
return -1;
}
else
{
return 1;
}
}
private void FormationShapeSquad(Vector3 _StartPos, Vector3 _EndPos, float SizeObj, ref List<GameObject> ListObj)//this makes the formation upon start
{
float _NumberObj = ListObj.Count;
float _width = Mathf.Abs(_StartPos.x - _EndPos.x);
float _height = Mathf.Abs(_StartPos.z - _EndPos.z);
int Cols = 0, Rows = 0;
if (_width > SizeObj && _height > SizeObj)
{
float Acreage = _width * _height;
float _SumCanContain = Acreage / SizeObj;
if (_SumCanContain >= _NumberObj)
{
// OK
Debug.Log("OK");
Cols = (int)(_width / SizeObj);
Rows = (int)(_height / SizeObj);
}
else
{
// kiểm tra xem mảng có đựng vừa số Obj không
float Temp = Mathf.Sqrt(_NumberObj);
if ((int)(Temp + 0.5) != (int)Temp) // Phần thập phân lớn hơn 0.5
{
Cols = (int)(Temp + 1);
Rows = (int)(Temp + 1);
_width = Cols * SizeObj;
_height = Rows * SizeObj;
}
else
{
Cols = ((int)(Temp) + 1);
Rows = (int)(Temp);
_width = Cols * SizeObj;
_height = Rows * SizeObj;
}
}
}
else
{
// kiểm tra xem mảng có đựng vừa số Obj không
float Temp = Mathf.Sqrt(_NumberObj);
if ((int)(Temp + 0.5) != (int)Temp) // Phần thập phân lớn hơn 0.5
{
Cols = (int)(Temp + 1);
Rows = (int)(Temp + 1);
_width = (int)(Temp + 1) * SizeObj;
_height = (int)(Temp + 1) * SizeObj;
}
else
{
Cols = ((int)(Temp) + 1);
Rows = (int)(Temp);
_width = ((int)(Temp) + 1) * SizeObj;
_height = (int)(Temp) * SizeObj;
}
}
int cout = 0;
int _dirZ = ReverseToOne((int)(_StartPos.z - _EndPos.z));
int _dirX = ReverseToOne((int)(_StartPos.x - _EndPos.x));
float TempWeight = _StartPos.x;
float TempHeight = _StartPos.z;
for (int i = 0; i < Cols; i++)
{
for (int j = 0; j < Rows; j++)
{
if (cout < _NumberObj)
{
ListObj[cout].transform.position = new Vector3(TempWeight, 0f, TempHeight);
cout++;
TempHeight += _dirZ * SizeObj;
}
}
TempWeight += _dirX * SizeObj;
TempHeight = _StartPos.z;
}
}
private void FormationLine(Vector3 _StartPos, Vector3 _EndPos, float SizeObj, ref List<GameObject> ListObj)//this makes the formation upon start
{
float _NumberObj = ListObj.Count;
//float _distance = Vector2.Distance(new Vector2 (_StartPos.x, _StartPos.z) , new Vector2( _EndPos.x, _EndPos.z));
float _distance = Vector3.Distance(_StartPos, _EndPos);
int Row = 0, Col = 0;
float _width = 0, _height = 0;
/*if(_distance > SizeObj)
{*/
//Use Default value
float Temp = Mathf.Sqrt(_NumberObj);
if ((int)(Temp + 0.5) != (int)Temp) // Phần thập phân lớn hơn 0.5
{
Row = (int)(Temp + 1);
Col = (int)(Temp + 1);
_width = Row * SizeObj;
_height = Col * SizeObj;
}
else
{
Row = ((int)(Temp));
Col = (int)(Temp) + 1;
_width = Row * SizeObj;
_height = Col * SizeObj;
}
//Debug.Log("_distance " + _distance + " ; witdh = " + _width, gameObject);
if (_distance > _width)
{
//Debug.Log("Out Wrong _distance "+_distance+" ; witdh = " + _width , gameObject);
// Use dyamin setRTS
Row = (int)(Mathf.Ceil(_NumberObj / Row));
Col = (int)(_distance / SizeObj);
}
else
{
//Use default Arange => do not change col, row
// Handle StartPos and EndPpos same Pos (just Click, not drag Mouse)
if (_distance == 0)
{
Vector3 Dir = new Vector3(-1, 0, -1);
_EndPos += Dir;
}
}
int cout = 0;
Vector3 TempEndPos = _EndPos;
Vector3 TempStartPos = _StartPos;
for (int i = 0; i < Row; i++)
{
Vector3 Dir = _EndPos - _StartPos;
Dir = Dir.normalized;
Vector2 VTPT = new Vector2(Dir.z, -Dir.x);
VTPT = VTPT.normalized;
Debug.DrawLine(_StartPos, _EndPos, Color.yellow);
for (int j = 0; j < Col; j++)
{
if (cout >= _NumberObj)
{
break;
}
ListObj[cout].transform.position = TempStartPos;
cout++;
Vector3 _dir = TempEndPos - TempStartPos;
_dir = _dir.normalized;
TempStartPos += _dir * SizeObj;
TempEndPos += _dir * SizeObj;
}
if (cout >= _NumberObj)
{
break;
}
TempStartPos = _StartPos + new Vector3(VTPT.x, 0, VTPT.y) * SizeObj;
TempEndPos = _EndPos + new Vector3(VTPT.x, 0, VTPT.y) * SizeObj;
Debug.DrawLine(_StartPos, TempStartPos, Color.red);
Debug.DrawLine(_EndPos, TempEndPos, Color.green);
_StartPos = TempStartPos;
_EndPos = TempEndPos;
}
}
#endregion
private void formationShape()
{
if (Input.GetMouseButtonDown(0))
{
//Debug.LogWarning("Click Button Down");
//startClick = Input.mousePosition;
RaycastHit hit;
m_ray = m_MainCamera.ScreenPointToRay(Input.mousePosition);
Physics.Raycast(m_ray, out hit, 1000f);
startClick = hit.point;
m_BoxSelected.m_baseMin = startClick;
}
if (Input.GetMouseButton(0))
{
RaycastHit hit;
m_ray = m_MainCamera.ScreenPointToRay(Input.mousePosition);
Physics.Raycast(m_ray, out hit, 1000f);
endClick = hit.point;
m_BoxSelected.m_baseMax = endClick;
//FormationShapeSquad(startClick, endClick, 1.5f, ref unitsList);
FormationLine(startClick, endClick, 1.5f, ref unitsList);
}
if (Input.GetMouseButtonUp(0))
{
//formationMaker3(startClick, endClick, 1.5f, ref unitsList);
}
}
void Update()
{
formationShape();
}
private void OnDrawGizmos()
{
Gizmos.DrawWireCube(m_BoxSelected.m_Center, m_BoxSelected.m_Size);
}
}
public class BoxSelected
{
public BoxSelected() { }
public Vector3 m_baseMin, m_baseMax;
public Vector3 m_Center
{
get
{
Vector3 _center = m_baseMin + (m_baseMax - m_baseMin) * 0.5f;
_center.y = (m_baseMax - m_baseMin).magnitude * 0.5f;
return _center;
}
}
public Vector3 m_Size
{
get
{
return new Vector3(
Mathf.Abs(m_baseMax.x - m_baseMin.x),
(m_baseMax - m_baseMin).magnitude,
Mathf.Abs(m_baseMax.z - m_baseMin.z)
);
}
}
public Vector3 m_Extents
{
get
{
return m_Size * 0.5f;
}
}
}
Solution for FormationShapeSquad and FormationLine
Sorry for my bad English!

Programatically design chess board cubes in unity

I'm new to Unity and am trying to create the chess board background in unity. I need the scene to be full of cubes using the prefab I created. When the counter is even, the cube is set to black else to red. I don't know what is going on really because nothing is showing up when z is 0. This is my code..
public GameObject pre;
public int counter = 0;
public int worldWidth = 20;
public int worldHeight = 20;
private float positionX;
private float positionY;
void Start()
{
chessBoardCube = Resources.Load<GameObject>("Prefabs/pre");
positionX = -11.24f;
positionY = 4.8f;
counter = 0;
}
void Update()
{
for (int x = 0; x < worldWidth; x++)
{
for (int z = 0; z < worldHeight; z++)
{
if (counter % 2 == 0)
{
GameObject block = Instantiate(pre, Vector3.zero, Quaternion.identity) as GameObject;
block.renderer.material.color = Color.black;
block.transform.parent = transform;
float xP = positionX * 3;
float yP = positionY * z;
block.transform.localScale = new Vector3(2, 2, 1);
block.transform.localPosition = new Vector3(xP, 0);
}
else
{
GameObject block = Instantiate(pre, Vector3.zero, Quaternion.identity) as GameObject;
block.renderer.material.color = Color.red;
block.transform.parent = transform;
float xP = positionX * x;
float yP = positionY * z;
block.transform.localScale = new Vector3(2, 2, 1);
block.transform.localPosition = new Vector3(xP, 0);
}
}
counter++;
}
}
The positionX and positionY variables are the position that the prefab is set.
Any help would be appreciated.
Thanks!
I'd suggest something like this:
public GameObject pre;
public int worldWidth = 20;
public int worldHeight = 20;
public float cubeSize = 2;
private float positionX;
private float positionY;
private float positionZ;
void Start()
{
chessBoardCube = Resources.Load<GameObject>("Prefabs/pre");
positionX = -11.24f;
positionY = 4.8f;
positionZ = 0.0f;
}
//Probably unwanted in update
void Update()
{
for (int x = 0; x < worldWidth; x++)
{
for (int y = 0; y < worldHeight; y++)
{
GameObject block = Instantiate(pre, Vector3.zero, Quaternion.identity) as GameObject;
block.transform.parent = transform;
if(x%2 == 0) {
if(y%2 == 0) {
block.renderer.material.color = Color.black;
} else {
block.renderer.material.color = Color.red;
}
} else {
if(y%2 == 0) {
block.renderer.material.color = Color.red;
} else {
block.renderer.material.color = Color.black;
}
}
float xP = positionX + x*cubeSize;
float yP = positionY + y*cubeSize;
block.transform.localScale = new Vector3(cubeSize, cubeSize, 1);
block.transform.localPosition = new Vector3(xP, yP, positionZ);
}
}
}
void generateBoard(){
float tempX = cubePrefab.transform.localScale.x;
float tempY = cubePrefab.transform.localScale.y;
float tempZ = cubePrefab.transform.localScale.z;
for (int i = 0; i < boardLength; i++) {
tempX = cubePrefab.transform.localScale.x;
for (int j = 0; j < boardWidth; j++) {
GameObject block = Instantiate(cubePrefab, parentTransform) as GameObject;
block.transform.localPosition = new Vector3(tempX , tempY , tempZ);
tempX += cubePrefab.transform.localScale.x;
if(i%2 == 0){
if(j%2 == 0){
block.GetComponent<Renderer>().material.color = Color.white;
}else{
block.GetComponent<Renderer>().material.color = Color.black;
}
}else{
if(j%2 == 0){
block.GetComponent<Renderer>().material.color = Color.black;
}else{
block.GetComponent<Renderer>().material.color = Color.white;
}
}
}
tempZ += cubePrefab.transform.localScale.z;
}
}

Categories