Few question on script optimization

Hi all,

I always try to give less reference calling for Unity Engine. In a post ReJ suggested that more script, more entry point and more load on Unity Engine. Now, I’m facing a problem that is happening due to script reference I think. I need your help to overcome this. Specially from ReJ.

Here it is: In my game I have a gun which is creating a bullet GO while it receiving Shoot MSG. This is using my own MSG passing system and not costly I assure you. I can represent my gun controller in that way:

var bulletPrefab : GameObject;
var theReticle : GameObject;
var fireRate : float = 0.2;

private var nextFire : float = 0.0;

function ReceiveMessage ( msgInfo : Message ){

	if ( msgInfo == Message.Shoot ){	
		
		if ( Time.time > nextFire ){

			dirToMove = (theReticle.transform.position - transform.position).normalized;
			
			var thisBullet : GameObject = Instantiate (bulletPrefab, transform.position, Quaternion.LookRotation ( dirToMove) );
		
		 nextFire = Time.time + fireRate;
	    }			
		return;
	}
}

While it’s receiving a msg from game controller that it’s need to fire then it’s creating an Instance of the bullet by setting position and direction. I also controlled the fire rate by timer as you can see.

Now the bullet:

var timeOut : int = 5.0;
var bulletSpeed : int = 100;
private var targetToLook : Transform;

private var dir : Vector3;

function Start () {

	Invoke("Kill", timeOut); 
	targetToLook = Camera.main.transform;
	dir = transform.forward;

}

function Update () {
	
	transform.LookAt ( targetToLook );
	transform.position += (dir * bulletSpeed * Time.deltaTime);
	transform.eulerAngles.z += 2000 * Time.deltaTime;

}

This GO has a child GO which is containing a plane. So, I’m just make it to look at the camera to be a billboard. Also moving forward to by a speed. We may optimize the Update function [you can suggest me].

Now, when I’m pressing the fire button from UI [I’m using a single Input manager which is optimized and it’s not costly - Thanks to ReJ for it in another thread], the FPS is dropping by 4-5 FPS at least.

This is the state that I’m getting while not firing the bullet

and this is the state while I have some bullet that already fired [may be 5-8].

So, the major difference that I’m getting is “mono-scripts> update: 14.5”
Some other also but this one is major I think.

Can anyone help me out the way which will help me not to drop my precious FPS?

Question #2:

Consider a script :

and another one is:

The main difference is, in the second script I have the Update function. What cost to Unity Engine of these scripts? Are they same to Unity or 2nd one is more due to Update function? I’m my opinion 2nd one should be more costly.

Any opinion? I think this will help other a lot in case of dynamic object creation.

Thanks to all.

There’s a few things you can do to optimize the Update function:

  1. Cache your transform. Whenever you use “transform” (or “animation”, or “camera”, or “renderer”) Unity is actaully searching through your components to find it. Add in:

var cachedTransform : Transform = transform;

And use cachedTransform instead of transform.

  1. Cache the bullet velocity. (dir * bulletSpeed) never changes, so you could cache that in the same way.

  2. Don’t use eulerAngles to change rotations (read it’s entry in the script reference). Use Transform.Rotate:

cachedTransform.Rotate(Vector3.forward * 2000 * Time.deltaTime);

All that being said, I doubt that’s what’s causing your frame drop. If you are using sprites for these bullets then you should definitely use a particle system for them. One draw call for each bullet is going to destroy your performance.

As for your second question, I’m not sure. It depends on whether Unity just ignores empty functions or not. Even if it doesn’t though, the performance difference would most likely be negligible.

Thanks Alex! :slight_smile: Ya, I already thought about update function optimization as you said. But particle system is more expensive then a single Billboard, isn’t it? If I use a particle emitter to show the bullet it will be more costly [correct me if I’m wrong].

For second question, consider both case. Like, update function has something to do and also it’s empty. My point is, if we use more callback function then it should be costly. But if we use a script to hold some value not for call back then what is cost? Same or not.

Thanks

A particle system basically just puts all the sprites in a single mesh so that they only consume one draw call for all of them. A particle system might be more expensive than a single billboard, but if you’ve got several of them then it will be much more efficient. For bullet sprites, you definitely want to be using a particle system.

Essentially you need to keep your draw calls under or around 30 to get decent performance, even if those draw calls are only for sprites.

For the Update script thing, I’m not quite sure what you’re asking. Are you talking about memory cost or speed cost?

Say, a particle system [you can suggest me which one is best], a script [to control the path and life time] attached in the bulletGO sprite. So, according to your suggestions, if I spawn 10 bullet they will consume 1 draw call to draw the particle. This is good save. But it will not save the mono-update call. Obviously this is a save and I’m going for it. Thanks for this help bro. :). Correct me if I’m going to do something wrong.

This is cost of speed as Unity need to call each reference one by one. Because they are producing C reference in back ground and keeping and calling it. So, It should be like this:

  1. Bullet.js - They will create a class like named Bullet.
  2. If create a sprite of Bullet then it will create Bullet b1 = new Bullet() [I’m assuming]

So, the cost trade off is here:

Bullet has all virtual function to call like “Update”. If it call Update though it is not in Bullet.js [no update function] then there is no difference between my first Bullet code and 2nd Bullet code [which have Update function]. Which mean if I add a script then it will keep calling all call back though it has in script or not. I need to know this. I think a Unity guy can give the clear ans. :). I’m hopping they Unity sort that. :slight_smile:

For the particle system, you could probably try Brady’s Sprite Manager that he just posted. That should do what you want.

And yes, with a particle system, 10 bullets will consume 1 draw call. 1000 bullets will even consume 1 draw call (note that even though it’s one draw call, there is still processing to do for each one).

For the Update thing, you probably will incur an overhead of a function call whether or not there is an Update function. However, that overhead is (most likely) negligible, so you shouldn’t worry about it.

I had a similar question as the original poster about the cost of having additional (but very simple or even empty) scripts with Update functions within. The cost seems to be fairly high, and you should ideally try to keep as much of your operations as you can in as few scripts as possible.

For instance, for the project I’m currently working on I wanted to be able to spawn a number of particles/projectiles, each of which was a simple billboard that had a script attached to it to animate its movement. This approach turned out to be rather slow. I know part of this is due to the large number of draw calls, but I decided to test what I could do scriptwise first. I rewrote the system so that all of my projectiles were spawned and animated by a single script via arrays and loops. The number of gameobjects/draw calls did not change of course, but my framerate increased quite noticeably.

I now plan to rework the system again and use a particle system instead of seperate gameobjects to bring my draw calls down as well, but the reduction in the quantity of scripts running simultaneously was a major gain already.

Thanks Animator. :slight_smile:

That was my point about script. So, you already have faced that problem ;). This is very SAD that, we need to add a script to to make a GO billboard. Why Unity doesn’t give a option to make it billboard? They are giving 3D Text etc etc but Billboard is more important. This will SAVE a lot for iPhone type device.

Please Unity guy can we see it soon!!! So, for this condition like bullet/object that need to spawn on demand we should follow some steps:

  1. We should manage all of these in a single manager script that will spawn, animate and destroy.
  2. We should use object pooling system, like: at the starting of the game we can create bunch of it and then re-use it not create - destroy.
  3. We should use particle instead of plane mesh to represent it as it will take one draw call to draw all bullet.

@Animator: Did you use some looping in Billboard manager to animate and reposition the billboard? If it high then it will kill FPS. or any other idea. :slight_smile:

@ReJ: Can we get some clearance from you? You know what is going on behind the scene. :slight_smile:

Thanks All.

My understanding is Particles can have colliders, and particles can render as billboard. So what is the problem?

Check out the particle systems talk here, too:
http://unity3d.com/support/resources/unite-presentations/forest-talks-particles
pretty cool stuff!

Thanks, I’m going try on that. :slight_smile:

Yes, it’s better for performance.
You could try renaming Update() in your bullet class to something like MyOwnUpdate(). Then once you instantiate new bullet object put it into some container inside your BulletManager. Implement Update() function in BulletManager so it iterates over bullet’s container and calls MyOwnUpdate() for each bullet. That will reduce number of C->Mono calls and will keep your GO logic as usual.

That’s not necessary, but would help performance in a way that GarbageCollector would run collection phase less often.

Yes. Plus it helps that particle system will orient particles automatically and you don’t need to do that manually in your scripts (like you do with Billboards in the first post)

Btw, you should try “iPhone Script Call Optimization” in Project Settings | Player if you haven’t done so. It makes calls to the engine faster (but not the other way around, so you still need to reduce number of scripts with Update() function)

Thank you very much ReJ. :). Thanks to clear in deep. Actually, I was expecting an answer from you so that, we can understand behind the scene.

So, less virtual call is less C-> mono call. That was the point I need to clear.

Thanks all to share your vital experience.

Thanks ReJ again.

No, virtual calls and calls where engine have to call into “scripts” (ones I call C to Mono or C → Mono) are different things.

Calls where engine have to call into “scripts” are just those named “Update”, “FixedUpdate”, "Start’, “OnAwake”, “OnApplicationQuit” and several other callbacks (functions which names starts with “On”)