Multiple scripts vs One Script, controlling 200 gameobjects

Sorry if my title is misleading, hard to explain this shortly.

I planning to make an animal safari game. So my question is that will have less load for the frame rate to have one script control 200 game objects or have 200 gameobjects controlled independently by their script.

Not sure if it makes a difference for 200 units, but having one script control them all is the more performant solution, since each script that is a Monobehaviour needs to be called and has some overhead. When controlling tons of units, you want to write one manager script that does it for all of them. However, i’m not entirely sure if 200 classifies as “a ton”, so either way should still be fine.
If you are very concerned for performance (for example if you target mobile), you could implement the animals using DOTS, which can easily handle tens of thousands and upwards of a hundred thousand units on a decent computer. However, it’s data oriented programming, so learning how it works will take some time.

I’m not sure how much faster it is, but I did it recently when I had 400 calls to something. I changed it to a while loop coroutine.

You will have to have extra code to deal with situations like when things are enabled/disabled, so they are removed from the array.

Essentially, you are asking what is more performant: attaching a script with a specific method (let’s call it ‘doSomething’) to 200 objects, or use a single Controller script that runs that method once for each of the 200 objects it manages.

If you are really good at programming, the latter (single script with managed objects) will be slightly faster. But you need to realize that the invocation to ‘doSomething’ also happens inside the controller, and there is very little - if any - processing advantage to having it done in a single looping script vs during Update() - this is because you still need to iterate a list of objects and get their context - which is precisely what Unity’s Update Loop does (Unity Caches all active Update() methods for very fast access). The small performance boost you can get when using thousands of objects configured that way is usually due to other factors that accumulate. So if you implement doSomething a part of your Update() and attach that to 200 objects, you’ll lose only a tiny bit of performance but gain a lot of flexibility and ease of maintenance.

[Note: there is some dependence as to the targeted platform here. If you are targeting mobile devices, or devices with small processor caches in general, the ceiling when managing objects noticeably surpasses Update() may lower]

In any event, the gains a are very small compared to the inflexibility of your code such a controller incurs. Generally speaking, you are engaging in premature optimization. Only resort to this kind of code design when

  1. your performance requires optimization and
  2. the Profiler indicates that invocation (not execution) of your Update() is an issue.
1 Like

Okay let me add a little bit of context, lets say I want to constantly check a status of the animals to performa an action.
Do i have a controller script monitor 200 animals status and perfrom the required action of each
OR
Have a script attached to each of the 200 animals tha montiors their own status and performs their required action
The checking of status would be done in Update

Using a controller script would save you the overhead that comes from Update(). I don’t remember how much of an impact that makes now though. Unity has made performance improvements since the blog article comparing large scale Update() calls to a single manager script.

If my choice had to be between the two of them I would take the same approach as @Stardog . Create a manager and have the code in a coroutine. That way you can spread the processing of the animals across multiple frames.

If I were allowed to choose outside of them though I would look into Unity DOTS.

Well, perhaps we are mixing goals here. If the only reason you are creating the controller is to increase performance, don’t do it. A count of 200 units is much too low for any meaningful performance gain. Use a controller to implement cross-unit behaviour, like herds. As Ryiah and Stardog mention, a controller may also be helpful if you can spread out status checking over multiple frames (again, a cross-unit function), but you seem to indicate that status checks should happen every frame for every unit.

If the animals already have scripts attached that implement Update() (e.g. to control their animation), don’t do it - adding the controller in this case will actually slightly increase the performance cost.

It helps to remember that Unity has gone to great lengths to tweak the performance of invoking Update() and some other ‘magic’ methods like Start() - basically all methods that Unity can invoke without you declaring them ‘public’. Unity caches these in a list, and invoking these methods does not require any introspection or reflection. Since the code for status checks must be run no matter if it’s implemented on the animal or controller, the controller version only saves the very few cycles required for the Update() invocation itself.

The function of controllers usually is to add cross-unit abilities. Using it to increase performance only makes sense in very specific cases (e.g. object pooling).

1 Like