Standalone_Optimization.pptx
- Количество слайдов: 24
Разработка крупного standalone проекта на Unity улучшаем производительность
Кто мы такие
• Клиентская игра под Windows и Mac • Авторитарный сервер, тоже на Unity • Игровая сцена = 2000+ объектов со скриптами • Команда ~ 40 человек
Оптимизация UNITY ТОРМОЗИТ
Профайлер
Профайлер [Used. Implicitly] private void Update() { var updatables. Count = updatable. Objects. Count; for (int i = 0; i < updatables. Count; i++) { var item = updatable. Objects[i]; Profiler. Begin. Sample("MY_"+item. Get. Type(). Name+". Update"); item. Update(); Profiler. End. Sample(); } }
Профайлер выключен
Профайлить в файл private void Update() { if (Time. frame. Count % 300 == 1) { var file. Name = Generate. File. Name(); Profiler. enabled = false; //Освобождаем старый файл var log. File = Path. Combine(folder. Full. Name, file. Name); Profiler. log. File = log. File; Profiler. enabled = true; //Создаем новый файл } } http: //pastebin. com/kt. Vgrxyq
Профайлить в файл Результат: http: //pastebin. com/kt. Vgrxyq
Профайлить в файл [Context. Menu("Load folder")] private void Update() { path = Editor. Utility. Open. Folder. Panel("profiler", ""); all. Files = Directory. Get. Files(path, "*. prf"); current. File = Pick. File(); Profiler. Add. Frames. From. File(all. Files[current. File. Id]); } http: //pastebin. com/kt. Vgrxyq
Garbage. Collector • Вызывается в любое удобное ему время • GC. Collect = • Поколения GC =
Источники мусора BAD Строки Var s = “A”+”B”+”C”+”D”; String. Format(“{0}{1}{2}{3}”, A, B, C, D); Void Update(){ text = Some. Field. To. String(); } GOOD String. Builder. Length = 0; String. Builder. Append(‘A’). Append(‘b’). Append(‘c’). Append(‘d’); Int Some. Field { get{return_inner; } set{ if(field=value) return; text = Some. Field. To. String(); } }
Источники мусора BAD Замыкания Void Subscribe() { Var stuff = Get. Stuff(); other. On. Some. Event += t => Do. Something(Stuff) } Void Do. Something(T t, Tstuff) { stuff. Do(t); } GOOD Void Subscribe() { other. On. Some. Event += t => Do. Something(t) } Void Do. Something(T t, Tstuff) { Var stuff = Get. Stuff(); stuff. Do(t); }
Источники мусора BAD LINQ GOOD List<T> selection; Void On. Shift. Drag. Gropped() { selection = selection. Union(new. Selection) //ext. Distinct(). To. List(); //new } Void On. Shift. Drag. Gropped() { foreach(var item in new. Selection) { if(!selection. Contains(item) {selection. Add(item) } } BEST Hashset<T> selection;
Кодогенерация Source. Assembly. dll T 4 Mono. Cesil Generated. Code. CS Augmented. Assembly. dll
Кодогенерация T 4 VISUAL STUDIO Compile TempUnity. VS_binDebugAssembly-CSharp. dll UNITY Compile Generated. File. CS VISUAL STUDIO T 4 processor
T 4 How. To <#@ template debug="true" hostspecific="false" language="C#" #> <#@ output extension="cs" #> <#@ assembly name="$(Solution. Dir)TempUnity. VS_binDebugAssembly-CSharp. dll" #> <#@ import namespace="System. Reflection" #> <#@ import namespace="So. H. Common. Data. Presentation. Curve. Code. Generation" #> using System; using System. Collections. Generic; using So. H. Common. Bit. Stream. Data. Types; <#@ Директивы процессора #>
T 4 How. To partial void Create. Updaters(object component, List<ICurve. Updater> result) { <# foreach(Type t in classes) { #> if (component is <#=t. Name#>){ result. Add. Range(Create. Updaters(( <#=t. Name#>)component)); return; } <# } #> throw new Invalid. Operation. Exception(component. Get. Type (). Name + "should have [Generate. Curves] attribute"); } <# код который выполнит шаблон #> <#= переменная, значение которой подставится в результат #>
T 4 How. To – сгенерированный код partial void Create. Updaters(object component, List<ICurve. Updater> result) { if if if if if (component (component (component (component (component is is is is is Battle. Statistic) Buffable. Aspect) Building. Target. Aspect ) Double. Progress. Bar. Aspect ) Fog. Object. Aspect) Influence. Container ) Interaction. Aspect ) Outpost) Pingometer) Player. Resources) Projectile. Network. Channel ) Shop. Aspect) Side. Changer. Aspect ) Squad. Target. Aspect ) Undead. Building. Aspect ) { { { { { result. Add. Range(Create. Updaters(( Battle. Statistic)component)); result. Add. Range(Create. Updaters(( Buffable. Aspect)component)); result. Add. Range(Create. Updaters(( Building. Target. Aspect )component)); result. Add. Range(Create. Updaters(( Double. Progress. Bar. Aspect )component)); result. Add. Range(Create. Updaters(( Fog. Object. Aspect)component)); result. Add. Range(Create. Updaters(( Influence. Container )component)); result. Add. Range(Create. Updaters(( Interaction. Aspect )component)); result. Add. Range(Create. Updaters(( Outpost)component)); result. Add. Range(Create. Updaters(( Pingometer)component)); result. Add. Range(Create. Updaters(( Player. Resources)component)); result. Add. Range(Create. Updaters(( Projectile. Network. Channel )component)); result. Add. Range(Create. Updaters(( Shop. Aspect)component)); result. Add. Range(Create. Updaters(( Side. Changer. Aspect )component)); result. Add. Range(Create. Updaters(( Squad. Target. Aspect )component)); result. Add. Range(Create. Updaters(( Undead. Building. Aspect )component)); throw new Invalid. Operation. Exception (component. Get. Type(). Name + "should have [Generate. Curves] attribute" ); } return; } return; } return; } return; } return; }
T 4 How. To – сгенерированный код Самые популярные • • • List<T>, T[] Dictionary<string, T> А есть еще: • Hash. Set<T> и Sorted. Set<T> • Sorted. List<TKey, TValue> • Sorted. Dictionary<TKey, TValue> • Linked. List<T> • Stack<T> и Queue<T> Умные структуры данных и тупой код работают куда лучше, чем наоборот. // E. Raymond
Collections time Remove Add Contains Iterate List O(n) FAST Dictionary O(1)/O(n) FAST Hash. Set O(1) SLOW Sorted. Set O(log n) O(1) SLOW Sorted. List O(n) O(log n) FAST O(log n) O(1)/O(n) SLOW O(1)* O(1) O(n) FAST Sorted. Dictionary Stack/Queue * Удаляет элемент из коллекции
Collections time ticks size
Еще советы • Кэшируйте все подряд. GO, промежуточные вычисления, ссылки на монобехи. • Там, где вам не нужен расчет в 3 D – не делайте его • Не делайте лишних операций с векторами(структурами), пользуйтесь конструктором • Не используйте Debug. Log без надобности • If работает быстрее чем хитрая формула. Хитрые формулы оставте для шейдеров • Пользуйтесь асинхронными операциями Load. Level. Async и Resources. Load. Async • Пользуйтесь быстрыми проверками чтобы отсеить ненужное: AABB или евклидово расстояние • Пользуйтесь Buffer. Copy для быстрого копирования
Спасибо за внимание
Standalone_Optimization.pptx