IPhone Optimization Tips

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
(New page: *Ragdolls make the game significantly slower. Give the player the option to use ragdolls or not. *Skinned Mesh Renderer: **Set Quality to 1 Bone **Uncheck Skin Normals *Set iPhone Script C...)
 
m (Text replace - "</javascript>" to "</syntaxhighlight>")
 
(11 intermediate revisions by 3 users not shown)
Line 6: Line 6:
 
*Don’t play new compressed music at the middle of the game, it freezes the game for a short duration. Play it at scene initialization instead.
 
*Don’t play new compressed music at the middle of the game, it freezes the game for a short duration. Play it at scene initialization instead.
 
*Remove most (or all) lights from your scene. Use baked lighting instead.
 
*Remove most (or all) lights from your scene. Use baked lighting instead.
*In Project Settings > Time: Set Maximum Allowed Timestep to 0.1 bringing the game’s framerate to at least a guaranteed 10 fps minimum.
+
*In Project Settings > Time: Set Maximum Allowed Timestep to 0.1 bringing the game’s framerate to at least a guaranteed 10 fps minimum, assuming your bottleneck is coming from the physics. Use the profiler to find out where your bottleneck is.
 +
* Keep drawcalls under 20 if at all possible
 +
 
 +
 
 +
== Scripting tips: ==
 +
* Avoid SendMessage() calls, create a script/class variable to hold a reference to the specific scripts you want to call, and use a standard method call. Method calls are ~100x faster than SendMessage()!
 +
* Avoid Find or GetComponent type calls during normal runtime if at all possible, use script variables to hold references.
 +
* initialize script variables in Awake()
 +
 
 +
For example in Javascript:
 +
 
 +
<syntaxhighlight lang="javascript">
 +
 
 +
var myScriptRef : MyScriptName;
 +
var anotherScriptRef : AnotherScriptName;
 +
var playerGO : GameObject;
 +
 
 +
function Awake() {
 +
  myScriptRef = FindObjectOfType(MyScriptName);// returns the first active instance of MyScriptName script in the scene/level
 +
  if(myScriptRef == null)
 +
Debug.Log("ScriptName::Awake() myScriptRef - MyScriptName is not found!  Key function NOT possible!");
 +
 
 +
  var gameObjectFind : GameObject = GameObject.Find("MyGameObject");
 +
  if(gameObjectFind == null)
 +
Debug.Log("ScriptName::Awake() gameObjectFind - MyGameObject is not found!  Key function NOT possible!");
 +
  else {
 +
anotherScriptRef =  gameObjectFind.GetComponent(AnotherScriptName);
 +
  }
 +
 
 +
  playerGO = GameObject.FindWithTag("Player"); // finds my player object using the GameObject.tag field
 +
  if(playerGO == null)
 +
Debug.Log("ScriptName::Awake() playerGO - Player is not found!  Key function NOT possible!");
 +
}
 +
</syntaxhighlight>
 +
 
 +
* Limit FixedUpdate function complexity, perform most of your game processing in Update or LateUpdate
 +
* process player input (touches, accelometer, etc...) in Update
 +
* use timed and framerate function calling to reduce heavy processing every frame.  For example, instead of processing an entire array of gameObjects every frame, create a coroutine, and call it on a frame schedule. 
 +
* Ensure complex coroutines aren't called multiple times in a single frame
 +
 
 +
 
 +
In Javascript:
 +
<syntaxhighlight lang="javascript">
 +
var fixedFrameProcessingRate : int = 10; // we'll use every 10 frames
 +
private var currentFrame : int = 0;
 +
private var frameImCurrentlyProcessing : int = 0;
 +
 
 +
function Update() {
 +
  // let's call DoComplexProcessing based on the setting fixedFrameProcessingRate
 +
  if(Time.frameCount >= currentFrame) {
 +
      DoComplexProcessing();
 +
      currentFrame = Time.frameCount + fixedFrameProcessingRate;
 +
  }
 +
 +
  // this method will only execute once during a given frame
 +
  DoMeOnlyOncePerFrame();
 +
}
 +
 
 +
function DoComplexProcessing() {
 +
  // do something complex here
 +
}
 +
 
 +
function DoMeOnlyOncePerFrame() {
 +
  if(frameImCurrentlyProcessing == Time.frameCount)     
 +
    return;
 +
  else {
 +
    frameImCurrentlyProcessing = Time.frameCount;
 +
    // do something complex here
 +
  }
 +
}
 +
</syntaxhighlight>

Latest revision as of 20:52, 10 January 2012

  • Ragdolls make the game significantly slower. Give the player the option to use ragdolls or not.
  • Skinned Mesh Renderer:
    • Set Quality to 1 Bone
    • Uncheck Skin Normals
  • Set iPhone Script Call Optimization to “Fast but no Exceptions”. Naturally, set it to “Slow and Safe” during debug.
  • Don’t play new compressed music at the middle of the game, it freezes the game for a short duration. Play it at scene initialization instead.
  • Remove most (or all) lights from your scene. Use baked lighting instead.
  • In Project Settings > Time: Set Maximum Allowed Timestep to 0.1 bringing the game’s framerate to at least a guaranteed 10 fps minimum, assuming your bottleneck is coming from the physics. Use the profiler to find out where your bottleneck is.
  • Keep drawcalls under 20 if at all possible


[edit] Scripting tips:

  • Avoid SendMessage() calls, create a script/class variable to hold a reference to the specific scripts you want to call, and use a standard method call. Method calls are ~100x faster than SendMessage()!
  • Avoid Find or GetComponent type calls during normal runtime if at all possible, use script variables to hold references.
  • initialize script variables in Awake()

For example in Javascript:

var myScriptRef : MyScriptName;
var anotherScriptRef : AnotherScriptName;
var playerGO : GameObject;
 
function Awake() {
   myScriptRef = FindObjectOfType(MyScriptName);// returns the first active instance of MyScriptName script in the scene/level
   if(myScriptRef == null) 
	Debug.Log("ScriptName::Awake() myScriptRef - MyScriptName is not found!  Key function NOT possible!");
 
   var gameObjectFind : GameObject = GameObject.Find("MyGameObject");
   if(gameObjectFind == null) 
	Debug.Log("ScriptName::Awake() gameObjectFind - MyGameObject is not found!  Key function NOT possible!");	
   else {
	anotherScriptRef =  gameObjectFind.GetComponent(AnotherScriptName);
   }
 
   playerGO = GameObject.FindWithTag("Player"); // finds my player object using the GameObject.tag field
   if(playerGO == null) 
	Debug.Log("ScriptName::Awake() playerGO - Player is not found!  Key function NOT possible!");
}
  • Limit FixedUpdate function complexity, perform most of your game processing in Update or LateUpdate
  • process player input (touches, accelometer, etc...) in Update
  • use timed and framerate function calling to reduce heavy processing every frame. For example, instead of processing an entire array of gameObjects every frame, create a coroutine, and call it on a frame schedule.
  • Ensure complex coroutines aren't called multiple times in a single frame


In Javascript:

var fixedFrameProcessingRate : int = 10; // we'll use every 10 frames
private var currentFrame : int = 0;
private var frameImCurrentlyProcessing : int = 0;
 
function Update() {
   // let's call DoComplexProcessing based on the setting fixedFrameProcessingRate 
   if(Time.frameCount >= currentFrame) {
      DoComplexProcessing();
      currentFrame = Time.frameCount + fixedFrameProcessingRate;
   } 
 
   // this method will only execute once during a given frame
   DoMeOnlyOncePerFrame();
}
 
function DoComplexProcessing() {
  // do something complex here
}
 
function DoMeOnlyOncePerFrame() {
  if(frameImCurrentlyProcessing == Time.frameCount)      
    return;
  else {
     frameImCurrentlyProcessing = Time.frameCount;
     // do something complex here
  }
}
Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox