纳金网

标题: Optimizing with Unity iPhone, the first three things I’ll do… [打印本页]

作者: 晃晃    时间: 2011-11-24 20:56
标题: Optimizing with Unity iPhone, the first three things I’ll do…


           Optimization is a bit of a black art when you’re dealing with an api or engine where you can’t profile the internals, and unity-iphone is no exception. I’ve collected here a few of tricks I’ve found that have helped me squeeze more performance out of my iphone projects.
           

            
         

           1. Do Less, (aka timeslicing)
         

           Lets be honest, it’s really easy to put lots of code in Update() or FixedUpdate() for a behavior, or have it called once a frame. However that means that no matter how fast that code is, it’s going to be  called at a rate of (hopefully) 30fps.
         

           Most of the time, you don’t need to do this. Take for example this pseudo-code of a homing script.
         





               view plain
              



               copy to clipboard
              



               print
              



               ?
              









                 public
               



               
              



                 class
               



                MyHoming : MonoBehaviour {   
              




               
            



                  
            



                public
               



               
            



                void
               



               Update() {   
            



                     
            


               // expensive targetting and not so expensive trajectory calculations in here
              


               
            



                     
            


               // currently called every frame
              


               
            



                  }   
            



              }  
            




           public class MyHoming : MonoBehaviour {

        public void Update() {
                // expensive targetting and not so expensive trajectory calculations in here
                // currently called every frame
        }
}
         

           Consider replacing it with this:
         





               view plain
              



               copy to clipboard
              



               print
              



               ?
              









                 public
               



               
              



                 class
               



                MyHoming : MonoBehaviour {   
              




               
            



                  
            



                public
               



               
            



                float
               



               targettingFrequency = 1.2f;   
            



                  
            



                public
               



               
            



                float
               



               trajectoryFrequency = 0.2f;   
            



                  
            



                public
               



               
            



                float
               



               trajectoryBlend = 1.0f;   
            



                  
            



                private
               



               Vector3 updatedTrajectory = Vector3.zero;   
            



                  
            



                private
               



               Vector3 currentTrajectory = Vector3.zero;   
            



               
            



                  
            



                public
               



               
            



                void
               



               Start()   
            



                  {   
            



                      InvokeRepeating(
            


               "DoTargetting"
              


              , targettingFrequency*Random.value, targettingFrequency);   
            



                      InvokeRepeating(
            


               "DoTrajectory"
              


              , trajectoryFrequency*Random.value, trajectoryFrequency);   
            



                      DoTargetting();   
            



                      DoTrajectory();   
            



                  }   
            



               
            



                  
            



                public
               



               
            



                void
               



               DoTargetting() {   
            



                     
            


               // search for targets here, we don't do it often because it's expensive
              


               
            



                  }   
            



               
            



                  
            



                public
               



               
            



                void
               



               DoTrajectory() {   
            



                     
            


               // trajectory isn't as expensive but it's not something we need to do every frame
              


               
            



                  }   
            



               
            



                  
            



                public
               



               
            



                void
               



               Update() {   
            



                     
            


               // Just interpolate values each frame
              


               
            



                      currentTrajectory = SetTrajectory(Vector3.Lerp(currentTrajectory, updatedTrajectory, Time.DeltaTime*trajectoryBlend);   
            



                  }   
            



              }   
            



              }  
            




           public class MyHoming : MonoBehaviour {

        public float targettingFrequency = 1.2f;
        public float trajectoryFrequency = 0.2f;
        public float trajectoryBlend = 1.0f;
        private Vector3 updatedTrajectory = Vector3.zero;
        private Vector3 currentTrajectory = Vector3.zero;

        public void Start()
        {
                InvokeRepeating("DoTargetting", targettingFrequency*Random.value, targettingFrequency);
                InvokeRepeating("DoTrajectory", trajectoryFrequency*Random.value, trajectoryFrequency);
                DoTargetting();
                DoTrajectory();
        }

        public void DoTargetting() {
                // search for targets here, we don't do it often because it's expensive
        }

        public void DoTrajectory() {
                // trajectory isn't as expensive but it's not something we need to do every frame
        }

        public void Update() {
                // Just interpolate values each frame
                currentTrajectory = SetTrajectory(Vector3.Lerp(currentTrajectory, updatedTrajectory, Time.DeltaTime*trajectoryBlend);
        }
}
}
         

            
         

           It looks a lot more complicated, but it’s really not. You’re still doing the same trajectory updates it’s just that they’re now being blended across multiple frames. I can’t stress how much performance can be saved by doing this to all of your update functions. If you haven’t done so already just do it now.
         

            
         

            
         

           2. Force garbage collection frequently.
         

           If you don’t, eventually there’ll be a huge spike when it does so automatically.
           

           Try dropping this script into an object in your scene:
         





               view plain
              



               copy to clipboard
              



               print
              



               ?
              









                 using
               



                UnityEngine;   
              




               
            





                class
               



               GarbageCollectManager : MonoBehaviour {   
            



                  
            



                public
               



               
            



                int
               



               frameFreq = 30;   
            



                  
            



                void
               



               Update()   {   
            



                     
            



                if
               



               (Time.frameCount % frameFreq == 0)   
            



                          System.GC.Collect();   
            



                  }   
            



              }  
            




           using UnityEngine;

class GarbageCollectManager : MonoBehaviour {
        public int frameFreq = 30;
        void Update()        {
                if (Time.frameCount % frameFreq == 0)
                        System.GC.Collect();
        }
}
         

           It won’t improve your fps, but it will cut down on the occasional spikes that memory management will cause.
         

            
         

            
         

           3. Triangle & Draw Call counts
         


            Stay under 7.5k tris
           

            Stay under 20 draw calls
           


            
         

           These are often preached as a gospel, I’d say it’s more of a guide to keep an eye on your art performance.
         




           If you go over 7.5k triangles, or over 20 draw calls it’s not the end of the world… you’re just
           
            likely
           
           to be bottlnecking yourself at submitting your graphics content to the graphics API.
         

           You can batch draw calls by sharing the same material across mutiple objects and also increase this further by marking objects as “static” when they’ll never move.
         

           But! Don’t forget that there are other factors not displayed here… for instance fill rate, when rendering scenes with overdraw and complex shaders.  
           
            The best way to track your total graphics performance is still through xcode instruments, and the debugger log with profiling turned on.
           


           Conclusion
         

           While these three are by no means the only tricks to getting unity to perform on an iphone, these ones are my first port of call when things start to slow. I’ve been told about a whole lot of other optimizations, such as managers instead of unity called Update functions, coroutines better than invokes… so forth but haven’t tried them yet.
         

           Anyone got any suggestions, techniques they’ve found saved them some performance that are different from the ones above?
         

作者: tc    时间: 2012-3-14 23:26
先顶上去,偶要高亮加精鸟!

作者: C.R.CAN    时间: 2012-3-15 23:18
响应天帅号召,顶

作者: 彬彬    时间: 2012-3-16 19:53

   

作者: C.R.CAN    时间: 2012-3-17 23:28
凡系斑竹滴话要听;凡系朋友滴帖要顶!

作者: 菜刀吻电线    时间: 2012-7-2 23:26
再看一看,再顶楼主

作者: C.R.CAN    时间: 2012-7-29 23:25
很有心,部分已收录自用,谢谢

作者: 菜刀吻电线    时间: 2012-9-24 23:25
跑着去顶朋友滴铁

作者: 晃晃    时间: 2012-9-30 23:26
水……生命之源……灌……

作者: 奇    时间: 2013-2-1 23:27
百度的叫度娘,网易的叫易娘,新浪内部还在为是叫新娘还是浪娘而争论不休!……不管你们是企鹅的额娘,豆瓣的伴娘,还是华为的伪娘,都要记得,淘宝才是你们的亲娘啊!亲!!

作者: 菜刀吻电线    时间: 2013-2-7 00:51
凡系斑竹滴话要听;凡系朋友滴帖要顶!

作者: C.R.CAN    时间: 2013-3-11 23:21
百度的叫度娘,网易的叫易娘,新浪内部还在为是叫新娘还是浪娘而争论不休!……不管你们是企鹅的额娘,豆瓣的伴娘,还是华为的伪娘,都要记得,淘宝才是你们的亲娘啊!亲!!





欢迎光临 纳金网 (http://go.narkii.com/club/) Powered by Discuz! X2.5