- Home /
Different timer in a list of gameobject
Hello !
I have a list that contains GameObject. This list is empty at it start. At each collision I add the gameObject collisionned into the list. This parts works pretty well.
What I want to add to this is : Everytime I add a new gameObject to my list, there is a timer attached to this, and when the timer is done the gameObject is removed from the list.
I can't do a global timer because every gameObject has to been handle separatly.
There is the code I already have (about adding gameObject into list) :
if (!GM.collisionTab.Contains(collision.gameObject))
{
GM.collisionTab.Add(collision.gameObject);
GM.compteurCollision++;
}
and later on the code I use it to change material, but it doesn't help the problem I have.
I have been thinking about doing an array/list of timers but i can't update each timer at the same time and separatly.
Also, I've been thinking about using coroutine but again, i'm not sure it would solve the problem.
The last thing I've been thinking is doing a class that contains a gameObject and a timer, with a method that would update the timer, but since i'm pretty new in this i'm not really sure I could handle this myself.
Thank you for your help ! :)
Answer by Staarter · Mar 17, 2018 at 12:18 PM
Hi @Dreaa !
You can use a coroutine, which you start each time you add a gameobject in your list :
if (!GM.collisionTab.Contains(collision.gameObject))
{
GameObject go = collision.gameObject;
GM.collisionTab.Add(go);
GM.compteurCollision++;
StartCoroutine(ChangeColor(go));
}
IEnumerator ChangeColor(GameObject go)
{
print("ENTER : " + go.name);
yield return new WaitForSeconds(2);
print("EXIT : " + go.name);
go.GetComponent<Renderer>().sharedMaterial.color = Color.white;
}
$$anonymous$$y god I wish Unity would just remove coroutines, people can easily write a better function that produces less garbage, especially with a custom update system.
For example, this could of easily been done in a way the OP wanted, using a Dictionary... like so.
public Dictionary<GameObject, float> timedList;
private List<GameObject> removalQueue;
void Awake()
{
removalQueue = new List<GameObject>();
}
void Update()
{
foreach ($$anonymous$$eyValuePair<GameObject, float> pair in timedList)
{
pair.value -= Time.deltaTime;
if (pair.value <= 0)
{
//Change material
removalQueue.Add(pair.key);
}
}
if (removalQueue.Count > 0)
{
foreach (GameObject go in removalQueue)
{
timedList.Remove(go);
}
removalQueue.Clear();
}
}
Yes thank's @RobAnthem ! I admit coroutines are not the best way to do this. But for lisibility and easiest reasons, i think it's a better choice, even if it's most expensive. Especially for begginers.
By the way, if you are so offensed to see coroutine running, for performance reasons i guess, it's better to use for loop than a foreach ?
I'd love to, but you can't for loop a dictionary without adding an extra layer containing your keys. I don't know why $$anonymous$$icrosoft hasn't added for looping on dictionaries, and just output the $$anonymous$$eyValuePair at the indice, but I guess that would require generics in the for loop, and might add more overhead. $$anonymous$$ainly because in my example, I needed access to both the key and the value, for the removal queue. If you have a better way of doing it though, I'd definitely be interested. I just don't like coroutines because of the overhead, and the added layer of complexity that isn't necessary. I've developed 2 full games, and a procedural generation app, and never found a legitimate call to use coroutines.
Technically since both Coroutines and Foreach loops use the IEnumerator interface, the only real overhead you'd be saving is the UnityEngine C++ side of it, but from what I understand, it creates extra garbage for each call to the coroutine.
Hi @RobAnthem and thank's for sharing !
I have some troubles with your solution. You can't do that :
pair.value -= Time.deltaTime;
We can't modify value of $$anonymous$$eyValuePair in a foreach loop. It cause some out of sync (see that : http://answers.unity.com/answers/409844/view.html)
I know we can't use for loop in a dictionary, but we can for a List.
Answer by Dreaa · Mar 17, 2018 at 04:20 PM
@Staarter Hello, and thank you !
I wasn't expecting Coroutine to work because new gO are added faster than the old one are deleted from the list. So I was thinking Coroutine wouldn't be able to work since it will have to do something like instantiate multiple Coroutine at the same time.
But apparently it works like a charm, and I thank you very much :)
@Dreaa, you're welcome ! When you start a coroutine with a gameObject as a parameter, you pass the pointer of this object. That means, if you remove this gameObject from your list while the coroutine is running, the coroutine will not loose the reference of the gameObject.
As you guessed, you instantiate multiple Coroutines, but it can be dangerous. For exemple if you want to stop a coroutine of a specific gameObject when you remove your this one from your list.
$$anonymous$$eep going ! And don't hesitate to show us your amazing work! ;)
Your answer
Follow this Question
Related Questions
A node in a childnode? 1 Answer
Need help with switch case in order/timed 0 Answers
A list in a class... Am I doing it wrong?? 0 Answers
Splitting text from lines into variables 0 Answers
Help with array/lists manipulation in Editor script 1 Answer