I’ve got a question about a thing, I try to explain it:
- I implemented an ingame time mechanic so that every “x” seconds I count a day change and every “y” days I change the season. As example: every 24 seconds pass a day and every 50 days I change the season; (24*50 = 1200 seconds from the season-change to the next one)
- In the scene I’ve got 1000+ objects that every season-change has to do a function (as example “DoSomething”) and atm this is doing in the Update() of each object: in the Update() I check the season change and if this happen I call the function DoSomething.
This mean that every Update() 1000+ objects do an “if” that will be true only every 1200 seconds.
I think that I can do a better thing. like when the season change I can call the DoSomething function of each object: is it true? It means that every 1200 seconds I’ve to cycle all the childs of my scene, check if the child is a particular child and then call the function.
What do you think about this?
Why don’t you just have the season-dependent code become a bunch of event handlers?
In their Start() you just register the handlers on the class that keeps the season info, so that every season change you can send the event and every object will be notified at once with no season check at all.
Certainly iterating over all the objects every 1200 seconds is going to be substantially more efficient. If you can record the list of objects in advance (rather than search the scene) it’ll be mildy faster.
Ultimately though if you have 1000 objects that need to change, in some way you have to do some work per object. You could start messing with coroutines that update once every 1200 seconds, but you’d still eventually hit the problem that a load of work happened.
So short answer - yes, you’re right. Use ‘FindObjectsOfType’ to find all objects with your component on, then iterate over them and call your function on each one.
Yes. Your later idea is better.
When the object is created, have it register itself with a manager-type object in the scene which adds it to a list/collection. That manager object should also be the one that determines the season, or should be accessible to the script that manages the season. And when the season changes, it should “inform” all the registered objects by calling a method on them.
This pattern and recommendation is mentioned in a Unity video: Unite 2013 - Internal Unity Tips and Tricks - YouTube
It’s simpler but slower to use FindObjectsOfType. It’s slow because it uses reflection, and on 1000 objects too. But if you’re just prototyping and testing a mechanic quick and dirty, that way might serve you well enough until it’s time to improve performance.
@Cryptomane’s recommendation also works. Instead of the script being added to a list, the “season manager” can have a public “SeasonChanged” event that each of those 1000 objects can subscribe to. And when the season changes, the “season manager” can call SeasonChanged(whateverdata you want to pass). In this case, the child will know information about itself (and you can pass information to it about the season), and it can react accordingly.
Learn about the syntax of C# events and event handlers here: https://unity3d.com/learn/tutorials/modules/intermediate/scripting/events
Which solution you choose depends on how you want to think about the objects. Is it easier to think about them when they’re passive and just managed centrally? Or do they manage and mutate themselves and are just informed? Which script is better equipped/has the data to cleanly perform the needed operations without the code turning into a mess?