Поскольку в настоящий момент обрели популярность работы с использованием функций замены текстур SetObjectMaterial(), считаю нужным расставить точки над i и оповестить о нескольких нюансах работы этой функции.
Для начала - немного теоретической части для общего понимания механизма рендера движком моделей, и начнем с рендера SA без учета мультиплеера.
Как многим известно, информация о моделях и их расположении подгружается движком из IDE (Item DEfinition file) и IPL (Item PLacement file) соответственно. Более того, масштабные модели имеют низкополигональную версию - LOD, который отрисовывается раньше основной модели и перестает отрисовываться при достижении нужного радиуса рендера.
Соответственно, механика процесса такова:
- игрок попал в зону отрисовки LOD: отрисовывается LOD.
- игрок из зоны отрисовки LOD переходит в зону основного рендера: LOD выгружается из памяти и в рендере более не участвует до следующего вызова, рендерится основная модель.
- игрок из зоны рендера основной модели переходит в зону рендера LOD: основная модель выгружается из памяти, рендерится LOD.
- игрок выходит из зоны рендера LOD: LOD выгружается из памяти и в рендере не участвует.
Созданные сервером объекты LOD не рендерят - серверу неоткуда брать информацию о нужном LOD. Поэтому схема упрощается:
- игрок попал в зону основного рендера: рендерится основная модель.
- игрок из зоны рендера основной модели выходит: основная модель выгружается из памяти (учитывая наличие стримера: оригинальная схема модели не выгружает, но жестко лимитирует их количество, выделяя память специально для них).
Как можно заметить, без необходимости модель не занимает места в ОЗУ, тем самым экономя ресурсы.
Основная проблема SetObjectMaterial (и производных, SetObjectMaterialText, к примеру) - она НЕ ВЫГРУЖАЕТ модель из ОЗУ. Схема рендера получается неполной:
- игрок попал в зону основного рендера: рендерится основная модель.
- игрок из зоны рендера основной модели выходит: основная модель НЕ ВЫГРУЖАЕТСЯ из памяти, загаживая стек.
Стек не бесконечен. В случае SA максимально возможное количество используемой ОЗУ колеблется в районе 1.6ГБ. В случае переполнения стека движок пытается обратиться к участку памяти, доступа к которому у него нет, вследствие чего клиент падает с ошибкой. Чрезмерное использование SetObjectMaterial еще больше увеличивает шансы выхода за пределы стека.
Посему один небольшой совет: используйте функцию только там, где это действительно необходимо.
UPD: говорят, что к SA:MP 0.3.7 утечку памяти пофиксили.
Disclaimer:
- использование данного материала без явного разрешения автора запрещено;
- использование данного материала без явного указания автора, даже при его явном согласии, запрещено.
В пост призываются гуру для уточнения, прав ли я и если нет - то где именно.