Gamasutra: The Art & Business of Making Gamesspacer
View All     RSS
July 29, 2014
arrowPress Releases
July 29, 2014
PR Newswire
View All
View All     Submit Event





If you enjoy reading this site, you might also want to check out these UBM Tech sites:


 
Unity Android Performance Optimization in Domingos – part 1
by satish chandra on 02/15/14 06:22:00 am   Featured Blogs

The following blog post, unless otherwise noted, was written by a member of Gamasutra’s community.
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.

 



We are TeaPOT Games, and we just released our award winning game – The Domingos on Google Play. It is a puzzle gam…

“Wait a minute, I’ve never heard of your stupid game before. Which award did u win? Best Game from the Great Nation of Grand Fenwick? “

Well, no, the web version of the game won the Excellence award in a Game Design Competition, held in India by Square Enix. Granted, it’s no Oscar, but the phrase “award winning game” sounds cool as long as you don’t say which award it is. So we are exploiting it :)

Anyway, in this post I will be covering few optimization tips for Unity 3D we implemented in the Android port of Domingos.

This article is aimed at (and hopefully will help) the Intermediate/beginner users of Unity 3D. If you are an Advanced/Expert user, you might as well close the tab, or better yet, read the post keeping an eye out for anything we missed.

It’s recommended that you play the game (The Domingos, link: http://goo.gl/aJUf85) to understand how certain aspects of the game work. If you don’t have an android device, have a look at the trailer on the google play page to at least understand what the gameplay constitutes.

1. Using InvokeRepeating instead of Update.
Unity’s mono functions like Update, LateUpdate, FixedUpdate, are not Functions per se. They are SendMessage calls from the unity engine to the respective game objects. They are by no means performance hampering, but you can earn some performance points by using InovkeRepeating instead.

How it is implemented: As you can see, the game has lots of dominos (some levels have 200+) toppling left, right and centre. Each domino has a script attached to it, which checks if the domino has fallen to the ground or not. If yes, it will make a light sound, and change a public Boolean flag to true- indicating that the domino has toppled. Depending on the type of domino, this flag will help determine the outcome of the level- level complete, or level failed.


Must... Topple... Dominos

Clearly, this has to be checked in each frame(or at least at regular intervals). So, if this code is placed in the Update function, it would mean that the unity engine has to do SendMessage on 200 game objects- this can’t be good.
Instead, we did this

function Start ()
{
//calling the invoke repeating on dominostatecheck function instead of putting all that code in
//the Update
InvokeRepeating("DominoStateCheck",0.02, 0.02);        
}

function DominoStateCheck ()
{
//checking if the domino has toppled if it hasn’t already
//if the y coordinate is less than 0.25, the domino is ruled as toppled. It’s a crude way, but it works.
if(dominoToppled==false&&transform.position.y<0.25)
{
//playing the domino topple sound
SoundManager.soundManager.PlayDominoFallSound();
//changing the toppled flag
dominoToppled =true;
}
}

To summarize, if you have an update function that doesn’t use Time.deltaTime in it, you can consider replacing the function with a InvokeRepeating  call, especially if you are bound to have high number of instances of that game object, just like in Domingos.

[Edit: according to this redditor, there is a even better way(albeit, a bit more complex) of doing this. check it out here: http://www.reddit.com/r/Unity3D/comments/1xz4wa/i_wrote_a_blog_post_on_some_of_the_techniques_we/cfg14m1]

2. Toggling isKinematic field on/off on rigid bodies.
Like I said, some levels of the game have more than 200+ dominos(play level 61). This means 200 small domino sized boxes that the game engine has to take care of, as they topple and slide on each other.
This will make an average android device hot enough to cook an omelette on its back. You might not like this – especially if you hate omelettes :)

Here’s the fix: After say, 0.5 seconds, the dominos will come to a rest, either flat on the ground, or slumped against another domino. But the game engine doesn’t know that the dominos have come to a ‘practical’ stop. It relentlessly applies gravitational force on a slumping domino, and calculating its collision parameters against the dominos it is in contact with – all for no visible result. I experienced a frame rate of 4fps on Samsung p3100 when I let the dominos topple through, prior to optimization.

So, after that said 0.5s, you check if the dominos have come to a stop. If they have, turn the isKinematic flag to true. This will cut the dominos off force and collision calculations

Code with comments:

function Start ()
{
InvokeRepeating("DominoStateCheck",0.02, 0.02);
//saving the position of the domino
prevPosition =   gameObjectTransform.position;
}

function DominoStateCheck ()
{
if(dominoToppled==false&& transform.position.y {
SoundManager.soundManager.PlayDominoFallSound();
dominoToppled =true;
//save the time when the domino was toppled
dominoToppleStartTime = Time.time;
}

//if the domino is not moving, and if some time had passed since the domino was toppled, we
//disable it
if(dominoToppled
&& Vector3.SqrMagnitude(transform.position- prevPosition)<0.01
&&Time.time> dominoToppleStartTime +0.5)
{
//this will make the rigidbody immobile for forces and collisions
rigidbody.isKinematic=true;
}
//saving the position for the next cycle
prevPosition =   gameObjectTransform.position;

}

Doing this will freeze the dominos, but we can activate them( toggling the isKinematic back to false) when we need them to act up again.

For example, in Domingos, there is certain kind of domino which explodes when toppled (play level 13). We call it - the Dyanimo, because we love squeezing two words into one. BTW, Domingo is Domino + amigo. Award winning games don’t name themselves, you know :)

So, when a Dyanimo topples, and explodes, it naturally has to push everything near it away, including the toppled dominos.

Code with comments:

//cast a physics.overlapsphere at the position of the dynamite domino in the
//Layer(http://goo.gl/bFei6H) of dominos to get the colliders of dominos nearby
disabledDominos = Physics.OverlapSphere (dyanimoPosition, radius, dominoLayer);
//cycle through the dominos and set isKinematic to false on them
for (i=0; i< disabledDominos.Length;i++)
{
disabledDominos[i].gameObject.rigidbody.isKinematic=false;
}

I believe one can use this technique in games with physics-centric mechanics and high object count.

I am going to write another post explaining in detail how the domino sequence drawing mechanic was implemented in the game.  It involves considerable amount of vector math. One look at that code will turn newbies into Math Doctors, or at least Math Nurses -perhaps neither.

Try our “award winning game” over here: 
https://play.google.com/store/apps/details?id=com.teapotgames.thedomingos
You can try the bread winner of our studio, our debut game- Total Parking, over here:
https://play.google.com/store/apps/details?id=com.teapotgames.totalparking

Follow TeaPOT Games
Facebook: http://goo.gl/EpIULi
Twitter: http://goo.gl/VV5T4p
Google+: http://goo.gl/HXs7am


Related Jobs

Activision
Activision — Seattle, Washington, United States
[07.29.14]

Software Engineer - Activision Seattle
Treyarch / Activision
Treyarch / Activision — Santa Monica, California, United States
[07.29.14]

Senior Environment Concept Artist - Treyarch (temporary)
Vicarious Visions / Activision
Vicarious Visions / Activision — Albany, New York, United States
[07.29.14]

Software Engineer-Vicarious Visions
Sony Online Entertainment, San Diego
Sony Online Entertainment, San Diego — San Diego, California, United States
[07.28.14]

UI Programmer, PlanetSide 2






Comments


Florian Putz
profile image
Nice articel, but I wouldn't do it that way. As far as I can see u constantly check for each stone if it has been toppled or not - even if it hasn't been touched by anything. U can avoid that by only tracking stones that have been touched or collided with something - just fire a OnCollide message and add the stone to a list. The list of stones-to-track will always be small because it only contains stones that are currently falling - until u stop and deactivate them - thus removing it from the list.

satish chandra
profile image
Overall, I agree with the idea. But few features in level design demanded some script to be running on the dominoes. Some of those features didn't make it to the final version of the game, so I'll give this another shot and see if i am getting better performance.

Adrian Mesa Pachon
profile image
Hi! I see you are using 0.02 as time interval for InvokeRepeating so you are updating your script in a lower frequency than 0.016, that is the common update frequency when your game runs at 60fps.

My doubt is if your performance gain is due to the fact you are updating at a lower frequency or because you are avoiding SendMessage overhead.

Have you done some tests using lower frequencies ?

satish chandra
profile image
no, its because we are avoiding the SendMessage overhead. we tried with 0.04 interval, and we got no visible(very little, if not none) performance increase. but we changed it back to 0.02 since we noticed a audio delay(naturally) with 0.04 interval, when it comes to the toppling sound of the dominoes.

Brian Kehrer
profile image
Was CPU a bottleneck on android devices?

satish chandra
profile image
In Domingos it is. Considering few levels have 200 + boxes.

Wes Jurica
profile image
Rigidbodies automatically go to sleep when they reach the sleep angular velocity and velocity thresholds. This stops all physics calculations until the object gets a force applied to it or collides with another rigidbody.

Martin Bell
profile image
This was my first thought.
Then I realised with a row of dominoes they may still all be touching each other (or close enough to form a contiguous island) so may not be put to sleep.

satish chandra
profile image
We fiddled with the sleep velocity and sleep angular velocity in the physics manager but we got little to no performance increase. when we manually toggled their kinematic fields, the performance jumped from 4-5 fps(on samsung p3100 with 50 + dominoes) to 20 fps. i think that the physics calculations will only be skipped when the said collision is between a kinematic rigidbody and a non kinematic rigidbody. but with multiple dominos, that wasn't the case. hope i am clear my explanation.


none
 
Comment: