Is having same script for over 100 Gameobjects good idea?

Hello,

I am new to the forums and unity scripting so I might get some stuff wrong.

The MAIN reason I am making this thread is because I want to make sure what I am doing is effective.

I am trying to make asteroids that spawn and move to the right from the left side of the screen kind of like stars in the night sky.

I made a Asteroid Spawner, that spawns the star prefab, and have another script in the star prefab that move it from left to right, the Aesteroid Spawner simply assigns the speed to the script inside the star prefab, to give it a bit of randomness. Now heres my main question IS IT A GOOD PRACTICE? because I am spawning about 50 stars (new one spawns in when it gets destroys after going out the screen), and is having script for each object a good practice? Specially when they do they same thing just with different settings? I can’t really think of another way. Unless I use Coroutines, which I never used (in this engine I mean), I got an idea what they do, but I don’t know if Coroutines, in this engine specifically is bad practice.

Sincerely, A random peron on the internet.

Yes this is standard practice. If you have that many objects and they are often being spawned and destroyed you should probably also look into object pooling.

2 Likes

imo this is not a good practice, if you’re talking only 50 simple objects on modern hardware it’s not gonna be a problem, but if you start having hundreds and thousands of stuff that need logic in the game you’re gonna have a bad time with everything having a monobehavior

What you can do is have a manager monobehavior that loops over all the asteroids and applies logic to the objects, if you post your asteroid script here I’ll be happy to explain how to convert it to work like that, I’m drawing a blank on a simple example.

2 Likes

I’m curious about this, wondering how much more overhead there is by doing it this way. All the objects have other components like colliders, rigidbodies, etc., and there’s no way to not have those (unlike the script), so would be interesting to know some comparisons performance and memory-wise. I often use a main script to control the logic of spawned objects, but some logic is easier to manage on the object itself…on that note, how would you test for (say) a collision from the master script?

Of course there are some stuff you have to do with a monobehavior like collisions or UI stuff, stuff that requires a unity callback.
but like @PraetorBlue said you can optimize that with pooling and also culling what ever you know isn’t gonna be called via a simpler check.
In a 2D asteroid example you can most likely get away with just a distance check if the asteroids aren’t too oddly shaped.

2 Likes

Heres the thing, each aesteroids have random speed so, there are no away to do that unless I use different scripts for each object (the only method I know of tbh,)

Absolutely the right way. The reason is a) that it is the UnityWay™, b) it is the simplest way, c) it will do what you want and keep your areas of concern very local and simple, and d) is very likely to be plenty performant. Don’t reach for crazy optimizations if you don’t need it. If a piece of code is supposed to control an asteroid, put it in a script and put it on the asteroid.

If you look into interfaces you can do all kinds of slick stuff like make your asteroids (or anything else) implement something like an IDamageable interface that lets them take damage. That way a bullet hitting any collider can go, “Hey, do you have an IDamageable? If you do, take 10 points of damage,” and the transaction is completely contained between the bullet and the target.

Enemy ships, asteroids, planets, other players, kitchen sinks, just about anyone can implement the IDamageable interface and your bullet will just damage them, all with no changes to the bullet code.

3 Likes

No, a random speed can also be set via a master script. The script would instantiate the asteroids and store them in an array, and in the same loop, set a random speed for the one just created and store it in another array. Then the movement loop uses the speed to move the asteroid.
Better yet, make an asteroid class which would have parameters like speed, size(?), point value(?), etc. Then you’d just have an array of those objects, and access the speed like
asteroid[25].speed = Random.Range(1, 20);

3 Likes

It depends on how you’re implementing all of these asteroids, you may want to look into ECS to make everything run efficiently especially if you’re planning on having all of these gameobjects do more than rotate and move. It might also help future proof your code in case you want to scale everything up and spawn even more stuff. Yes it’s fairly standard to do this for that many objects but at the same time there’s nothing wrong with planning ahead.

2 Likes

Just out of pure (morbid?) curiosity, is there no way to test for a callback like OnCollisionEnter from a script attached to a different GameObject, assuming you have a reference to the object you’re testing? Maybe some kind of listener?

I’ve look for a way to do that for a long time and found nothing, if you stumble upon a way please do share.

1 Like

Of course, just have that object fire a C# event inside OnCollisionEnter, and have your other script listen to that event.

He and I mean if you can listen to the OnCollisionEnter event from another script without the need for a monobehavior on the object, so I can receive all the messages inside a manager class directly.
the whole point of doing what we’re talking about is to not have the overhead of the monobehavior itself for each object.

Looks like you can expose them as events, interesting, but it still requires a script attached to the object in question (if I’m reading it right). So might as well just have it check within the object. Unless I’m not understanding it fully…

Check OnCollisionEnter on other GameObject - Unity Answers

A thing to note is how similar the 2 approaches are. Either way, the code isn’t duplicated, and the amount of data stays about the same. Say you have 30 lines controlling an object. If you put that script on 50 objects, you still only have 30 lines they all share. If each object has 6 variables, you’ve got 50 sets of 6 variables either way.

Unity is good at going through gameObjects and running Update. If you have a master script moving them all in a loop, you’re pretty much just doing the same thing. So the “do each item” overhead is about the same, just moved around.

I like to create a list of asteroids and have loop running Ast.doUpdateAction() since it seems easier to pause or other weird stuff, AND since it feels more like a normal program.

2 Likes

Another thing is to do a hybrid of script-on-object and a central list.

For instance, in my Rocket Raiders game each asteroid and enemy runs itself, as in tumbling and moving and wrapping and whatnot, but they all register with a central “interaction tracker” that basically once a frame decides if they hit the player, got hit by a bullet, etc., only because I am actually NOT using physics or collisions.

1 Like

Having a script on the object is often required for 2 reasons. As noted above, it’s required if you want Physics to notify you of collisions(*). It’s also nice to discover an item with a raycast. The script can store public int index; to know which asteroid you hit (otherwise you’d need to loop through them looking for a match).

Once you’re forced to put a script on it, you may as well add all variables – health, lifeLeft… and may as well put all asteroid functions there. Then the only question is whether to give them Start() and Update() or init() and update() which a master program must call.

(*)Unity Collisions don’t have event handlers where you can do asteroid1.onCollision+=myScript.asteroidHit. They only look for OnCollision on the hit object. That script seejayjames linked is just user code for a generic script “unity calls my oncollision, and I call a plug-in function someone gave me”. It’s basically this:

class CollisionPasser : Monobehavour {
  // call this on a collision:
  public Action<Collision, transform> ocFunc=null;

  void OnCollision(Collision c) {
    if(ocFunc!=null) ocFunc(c, transform);
  }
}

// in main script:
Asteriods[0].ocFunc = myAstColFunc;
1 Like

50-100 is fine, so long as you’re not being particularly wasteful of the CPU resources. When you get into the 1000’s you will start hitting performance issues. But it all depends on the actual hardware, and the code you’ve written. As already mentioned, a central manager that handles moving them all can perform better.

I’d just write it one way, then run it. See how it goes. Use the Profiler against a build of your game to really get the details on how this part of your code is performing. If it is working well, move on. If it is working like trash, rewrite/redesign, and try again. A simple moving asteroids script you could probably test several different approaches in just a few hours. Good luck!

3 Likes