How can I change the lights moving direction from the current light? - c#

The problem is in the LightsEffectCore when I make the array reverse.
The lights change direction but not from the current light it is on.
It's jumping to some other light index and change the direction from there.
And I want it to change the direction from the current light index.
If the light is now on index 5 and I change the direction then move from 5 to 4 and if I changed the direction again move from 4 to 5.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LightsEffect : MonoBehaviour
{
public List<UnityEngine.GameObject> waypoints = new List<UnityEngine.GameObject>();
public int howmanylight = 5;
public Generatenumbers gn;
public bool changeLightsDirection = 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)
{
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, 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;
}
}
}

You have to change your greenIndex as well, when you reversing the array. If you do not, then the new value at that index is going to be the one after the reverse, and that is why, it looks like it is jumping away.
If you want to avoid it jumping about, set the index to greenIndex=renderers.Lenght-greenIndex.
I could not test it out, please correct me if I am wrong.

Related

I am not able to successfully move my background with the script below

The script below is intended to move the background with the character. However, the background does not move at all when using this code and I suspect the problem may be somewhere in the LateUpdate function as once that is changed to update, the background continuously moves on its own, but not with the player.
public class ParallaxController : MonoBehaviour
{
Transform cam; // Main Camera
Vector3 camStartPos;
Vector2 distance;
GameObject[] backgrounds;
Material[] mat;
float[] backSpeed;
float farthestBack;
[Range(0f,0.05f)]
public float parallaxSpeed;
void Start()
{
cam = Camera.main.transform;
camStartPos = cam.position;
int backCount = transform.childCount;
mat = new Material[backCount];
backSpeed = new float[backCount];
backgrounds = new GameObject[backCount];
for (int i = 0; i < backCount; i++)
{
backgrounds[i] = transform.GetChild(i).gameObject;
mat[i] = backgrounds[i].GetComponent<Renderer>().material;
}
BackSpeedCalculate(backCount);
}
void BackSpeedCalculate(int backCount)
{
for (int i = 0; i < backCount; i++)
{
if ((backgrounds[i].transform.position.z - cam.position.z) > farthestBack)
{
farthestBack = backgrounds[i].transform.position.z - cam.position.z;
}
}
for (int i = 0; i < backCount; i++)
{
backSpeed[i] = 1 - (backgrounds[i].transform.position.z - cam.position.z) / farthestBack;
}
}
void LateUpdate()
{
distance = cam.position - camStartPos;
transform.position = new Vector3(cam.position.x, transform.position.y, 0);
for (int i = 0; i < backgrounds.Length; i++)
{
float speedX = backSpeed[i] * parallaxSpeed;
float speedY = speedX / 2; // if you close Y movement , set to 0
mat[i].SetTextureOffset("_MainTex", new Vector2(distance.x*speedX, distance.y*speedY));
Debug.Log("for loop works!");
}
}
}

Can't move Instatiated Object from queue, changes transform of prefab instead

I'm trying to make a "Mania" style game(like guitar hero). But i can't seem to get the Movement of the "notes" to work, I keep the notes in a queue and I dequeue the last note and change it's position to the top again. But for some reason it doesen't work with my "goodcubes". only the normal ones
The problem seems to be that the instead of moving the "goodCube" to the correct position it instead changes the transform of the prefab.
All "notes" are referred to as "Cubes" in script
for (int i = 0; i < backlog; i++)//how many rows to spawn
{
goodCubes.Enqueue(Instantiate(goodcube));
for (int j = 0; j < columns - 1; j++)
{
badCubes.Enqueue(Instantiate(cube));
}
}
//I check the player input and if it corresponds with a note in the correct row
//I have tested so both true and false option gets called
if (i == position)
{
GameObject good = goodCubes.Dequeue();
good.transform.position = spawnPoint;
spawnPoint += new Vector2(1 * rowOffset, 0);
goodCubes.Enqueue(goodcube);
}
else
{
GameObject badCube = badCubes.Dequeue();
badCube.transform.position = spawnPoint;`enter code here`
spawnPoint += new Vector2(1 * rowOffset, 0);
badCubes.Enqueue(badCube);
}
The full script
public int columus;
public GameObject cube;
public GameObject goodcube;
public event Action moveCubes;
[SerializeField] private int score = 0;
[SerializeField] private float rowOffset = 1;
[SerializeField] private float heightDifference = 1;
[SerializeField] private int backlog = 4;
private float SpawnHeight;
Queue<int> positions = new Queue<int>();
Queue<GameObject> badCubes = new Queue<GameObject>();
Queue<GameObject> goodCubes = new Queue<GameObject>();
private void Start()
{
for (int i = 0; i < backlog; i++)
{
goodCubes.Enqueue(Instantiate(goodcube));
for (int j = 0; j < columus - 1; j++)
{
badCubes.Enqueue(Instantiate(cube));
}
}
for (int i = 0; i < backlog; i++)
{
positions.Enqueue(SpawnRow(i * heightDifference));
}
}
int SpawnRow(float y)
{
int position = UnityEngine.Random.Range(0, columus);
Vector2 spawnPoint = new Vector2(-columus * rowOffset / 2f, y);
for (int i = 0; i < columus; i++)
{
if (i == position)
{
GameObject goodCube = goodCubes.Dequeue();
goodCube.transform.position = spawnPoint;
spawnPoint += new Vector2(1 * rowOffset, 0);
goodCubes.Enqueue(goodcube);
}
else
{
GameObject badCube = badCubes.Dequeue();
badCube.transform.position = spawnPoint;
spawnPoint += new Vector2(1 * rowOffset, 0);
badCubes.Enqueue(badCube);
}
}
return position;
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.D))
{
UpdateScore(0);
}
else if (Input.GetKeyDown(KeyCode.F))
{
UpdateScore(1);
}
else if (Input.GetKeyDown(KeyCode.J))
{
UpdateScore(2);
}
else if (Input.GetKeyDown(KeyCode.K))
{
UpdateScore(3);
}
} //inputcheck
private void UpdateScore(int input)
{
if (positions.Dequeue() == input)
{
moveCubes?.Invoke();
positions.Enqueue(SpawnRow(backlog * heightDifference + 1 * heightDifference));
score++;
}
else
{
moveCubes?.Invoke();
positions.Enqueue(SpawnRow(backlog * heightDifference + 1 * heightDifference));
score--;
}
}
I truly believe your issue is a typo in your code. That usually happens when you have variables with the same name. Your issue is that you are enqueuing the prefab goodcube and not the goodCube object:
GameObject goodCube = goodCubes.Dequeue();
goodCube.transform.position = spawnPoint;
spawnPoint += new Vector2(1 * rowOffset, 0);
//******HERE YOU ARE ENQUEUEING THE PREFAB goodcube AND NOT goodCube as your variable name suggests two lines above this line*****
goodCubes.Enqueue(goodCube);//INSTEAD OF goodCubes.Enqueue(goodcube);

How can I generate the units at the same time?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GenerateStairs : MonoBehaviour
{
[Header("Stairs Prefb")]
public GameObject stairsPrefab;
[Space(5)]
[Header("Platforms")]
public bool addPlatforms = false;
public GameObject platformsPrefab;
[Space(5)]
[Header("Settings")]
[Range(1, 20)]
public int numberOfUnits = 1;
public float delay = 3;
public int stairsNumber = 5;
public Vector3 stairsStartPosition;
public Vector3 stairSize;
public Vector3 stairsSize;
public float stepWidthFactor = 1f;
private Vector3 stairsPosition;
private GameObject stairsParent;
private int oldNumberOfUnits = 0;
// Use this for initialization
void Start()
{
oldNumberOfUnits = numberOfUnits;
for (int i = 0; i < numberOfUnits; i++)
{
stairsParent = new GameObject();
stairsParent.name = "Stairs";
StartCoroutine(BuildStairs());
}
}
// Update is called once per frame
void Update()
{
if(oldNumberOfUnits != numberOfUnits)
{
StartCoroutine(BuildStairs());
oldNumberOfUnits = numberOfUnits;
}
}
private IEnumerator BuildStairs()
{
for (int i = 1; i <= stairsNumber; i++)
{
stairsPosition = new Vector3(
stairsStartPosition.x,
stairsStartPosition.y + (i * stairsSize.y),
stairsStartPosition.z + (i * stairsSize.y) * stepWidthFactor);
GameObject stair = Instantiate(
stairsPrefab,
stairsPosition,
Quaternion.identity);
stair.tag = "Stair";
stair.transform.parent = stairsParent.transform;
stair.transform.localScale = stairSize;
yield return new WaitForSeconds(delay);
}
stairsParent.AddComponent<MoveObjects>().Init();
}
}
In the Start I'm doing a loop and start the Coroutine according to the numberOfunits.
It's working fine if numberOfUnits is 1. But is it's more then 1 for example 2 it's first creating the first set of stairs but then on the second "Stairs" parent it's creating only 1 stair. I don't want it to wait to finish the first Coroutine I want in the same time to create number of Coroutine's of stairs.
And I want also to add a gap between each stairs unit.
And also to make that in the Update if I change the numberOfUnits it will add/destroy more stairs units. All the stairs units should be Instantiate inside StartCoroutine.
You are mistaking how the coroutine works its not at thread. What is happening is your continually invoking the coroutine so its starting over and over again not creating a separate instance.
what you should do is create create a prefab and Instantiate that to do the work. My last remark was about threads but you wont be able to instantiate anything unless its on the main thread so the easiest way to get this done would be like so.
public GameObject yourGoWithAboveClassOnIt;
void Start()
{
oldNumberOfUnits = numberOfUnits;
for (int i = 0; i < numberOfUnits; i++)
{
Instantiate(yourGoWithAboveClassOnIt);
}
}
your prior class will remove this
void Start()
{
//oldNumberOfUnits = numberOfUnits;
//for (int i = 0; i < numberOfUnits; i++)
//{
stairsParent = new GameObject();
stairsParent.name = "Stairs";
StartCoroutine(BuildStairs());
//}
}

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 what's wrong with my instantiating algorithm?

I dont know if I can call this algorithm. But I am working on a game in which player will move in a circular path.
As you can see in the picture player is suppose to orbit the circle. And obstacle shall be instantiated in the circle.I am trying to first create the obstacle in first half(left to the long cube) and then in the second half. But things are getting created in the next half too when code is not supposed to do that. Also, it is showing argument exception error. Please have a look at my code and tell me whether my method is wrong or my formulas are wrong or anything else.
public class ObjectInstantiater : MonoBehaviour {
DataHolder dataholder;
GameObject Obstacle;
LevelData leveldata;
private int currentlevel=0; // default level starts from 0
private List<GameObject> Inactivegameobject = new List<GameObject>(); // this object can be used
private List<GameObject> Activegameobject = new List<GameObject>();
private int totalgameobjects;
private int firsthalfgameobjects, secondhalfgameobjects;
public float outerradius;
public float innerradius;
private bool shallspawnouterradiues = true;
// Use this for initialization
void Awake () {
dataholder = (Object)GameObject.FindObjectOfType<DataHolder>() as DataHolder;
Obstacle = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
leveldata = dataholder.Leveldata[0];
}
void Start()
{
Updateleveldata();
FirstHalf();
}
public int Currentlevel
{
get { return currentlevel; }
set { currentlevel = value;
leveldata = dataholder.Leveldata[currentlevel];//sets the level data
}
}
private void Updateleveldata() // this function gets called after a round
{
totalgameobjects = Random.Range(leveldata.MinimumObstacle, leveldata.MaximumObstacle);
firsthalfgameobjects = Mathf.RoundToInt(totalgameobjects / 2);
secondhalfgameobjects = totalgameobjects - firsthalfgameobjects;
}
private void FirstHalf()
{
Debug.Log(firsthalfgameobjects);
Vector3 pos;
if (Inactivegameobject.Count < firsthalfgameobjects)
{
for (int x = 0; x <= (firsthalfgameobjects - Inactivegameobject.Count); x++)
{
GameObject obs = Instantiate(Obstacle) as GameObject;
obs.SetActive(false);
Inactivegameobject.Add(obs);
}
}
float spawnangledivision = 180 / firsthalfgameobjects;
float spawnangle = 180f;
for(int x = 0; x < firsthalfgameobjects; x++)
{
float proceduralRandomangle = spawnangle;
proceduralRandomangle = Random.Range(proceduralRandomangle , proceduralRandomangle + 2f);
if (shallspawnouterradiues)
{
pos = new Vector3(outerradius * Mathf.Cos(spawnangle), outerradius * Mathf.Sin(spawnangle), 0f);
shallspawnouterradiues = false;
}else
{
pos = new Vector3(innerradius * Mathf.Cos(spawnangle), innerradius * Mathf.Sin(spawnangle), 0f);
shallspawnouterradiues = true;
}
spawnangle += spawnangledivision;
Inactivegameobject[0].SetActive(true); // set it to 0
Inactivegameobject[0].transform.position = pos;
Activegameobject.Add(Inactivegameobject[0]);
Inactivegameobject.RemoveAt(0);
}
}
private void SecondHalf()// No need to check this
{
if (Inactivegameobject.Count < firsthalfgameobjects)
{
GameObject obs = Instantiate(Obstacle) as GameObject;
obs.SetActive(false);
Inactivegameobject.Add(obs);
}
}
}

Categories