Optimization, Javascript and your game?

Just interested to hear any “must do” optimization with javascript code that people have come across in the past.

Anything at all, just interested to hear, and how it effected your game / how you resolved it.

Here’s a blog I wrote with what I had optimized for my game:

Unity mobile optimisation (iOS)

Couple of misconceptions on your blog:

  1. arrays themselves are not slow. What are slow are all-purpose js arrays. These are not the same as builtin typed arrays. Built in arrays and list are fast on js, faster than List (but only a tiny bit). This is because built in has sequential addressing, and list still needs to get the address of the next item in the list.

  2. transform does not actually incur a component lookup. They are cached in the engine. They didn’t used to be, but they are now. Caching it yourself is still going to be faster, but only if you access it thousands of times. It’s a good improvement.

for unity: I would like unity to optionally .useCache on each game object to force cache all components for that game object - if unity is listening.

This blog has been written pre-3.5, meaning transforms didnt cache yet, I should’ve stated that before posting.
I believe I stated though I was referring here to “all-purpose” (typeless) arrays though? If not, my bad, will update someday later.

I have a few simple techniques I run through.

In any sort of loop or anything accessed while gameplay occurs…

  1. Remove any GetComponent calls (.transform .gameObject .renderer .audio etc) and cache them.

  2. Avoid using transforms as much as possible, do as much of the math possible on variables, then apply to transforms.

  3. Do less of everything. I often try to turn 20 lines of code into 5 :slight_smile:

  4. Use multiply rather than divide (I don’t know if this actually makes a difference anymore).

  5. Avoid strings.

For things like figuring out how to trigger behavior on something hit with a raycast, I also like to keep all the objects that allow that behavior to have their colliders ObjectID’s stored in a hashtable. So I can get that ID, find it in the hash table, and it’ll tell me which object I hit by returning an integer, which is the index of an array that stores all of their behavior components.

Nope, even square roots aren’t much of a hit nowadays.

–Eric

Hi - Could you please give an example of point 2 and how it shouldn’t be used and an alternative example?

I use transforms to move gameobjects around a lot etc… is that what you’re referring to?

So, in using js, how do you set up your arrays?

There’s a cost associate with retrieving and setting position, rotation, scale, etc from the transform, so if you’re doing operations of transform.position several times per frame, it’s probably best to get the Vector3 once, perform everything on the vector 3, then set it when you’re done. For a single object, it’s not a huge deal, but if you have 30 or 40 objects on screen, it starts making a noticable lump in the profiler.

OK thanks… not sure how to do this, however (perform everything on the vector 3 then setting it). For example, what if I wanted to move an object, like so:

myGameObject.transform.Translate(Vector3.left*Time.deltaTime);

however, in shader programming, divide is costly on mobile still :slight_smile:

var trans:Transform = transform; //in start()

myVec = Vector3(-1, 0, 0) * Time.deltaTime;

trans.Translate(myVec);

I suppose? :slight_smile: I don’t think you should be optimising without first profiling, that’s a bad idea. Jamie is likely in his own pattern by now, so he does all these behaviours by default as he’s a “few games in”. If this is your first game, concentrate on a bug free and robust experience.

We used a halfrate script in Update for some heavy calculations that could be done every two, three or four calls.

var Halfrate: int;

function Update()
{
	if(Halfrate==1) // E.g. framerate 30 instead of 60
	{
		Halfrate=0;
		// Insanely heavy calculation here, e.g. objects-in-range-list
	}
	else 
	{
		Halfrate++;
	}

	// More code

}

Would you in that case not be better off calling a InvokeRepeating?
Just Wondering, not sure on that :slight_smile:

Yes, but then you also have to do a lot of cancelinvoke management.
But coroutines are quicker as well, yes.