PDA

Просмотр полной версии : Вопрос по добавлению объектов


Godwarlock
24.03.2016, 00:00
Всем привет. Создается к примеру 2000 объектов. Добавление объектов идет таким образом
var model:MovieClip = new (ApplicationDomain.currentDomain.getDefinition("object_" + id) as Class);//object_+id - это ссылка на экземпляр movieClip с картинкой.
addChild(model);
Скажите чем плох таков вариант, если подобных объектов очень много добавляется на сцену? Подскажите другие варианты реализации, более оптимизированные, если таково надо.

faraday
24.03.2016, 01:00
создавать мувиклип для хранения картинки - уже идея плохая. создаешь атлас всей графики. загружаешь одну png. из из нее по необходимости забирая нужные битмапы, кешируя.

Godwarlock
24.03.2016, 01:52
Атлас я так понимаю, это вектор битмап? А как это повлияет на производительность?

faraday
24.03.2016, 02:57
напиши конкретнее задачу, что содержат мувиклипы. если картинки, то все 2000 разные?

Godwarlock
24.03.2016, 04:23
Мувиклипы содержат 8 картинок(по 1 картинке на кадр). Активна только 1 картинка из всех 8, то есть она указывается в gotoAndStop(1-8). Каждый объект - это отдельная картинка. В зависимости от того, какой порядковый номер передается в параметр, устанавливается кадр мувиклипа, ну как и сказал указывается в gas.
если картинки, то все 2000 разные?
Нет. 60% из них могут быть одинаковые.
напиши конкретнее задачу
Единственная задача - это оптимизировать большую генерируемую карту. Я и обрезаю область вьюшки, обрезаю неактивные объекты в этой области и прописываю casheAsBitmap(что кстати дало немного фпсу), пробовал переводить картинку мувиклипа в битмапу и добавлял уже битмапу, а не мувиклип(что не дало никакой производительность, а только понизилась) и растеризацию по такой штуке http://www.ant-karlov.ru/iz-vektora-v-rastr.html проводил(то есть добавлял уже не мувиклипы, а цеплял из массива битмап, что понизило опять же производительность). И качество картинок обрезал до jpeg 60, без сглаживания. Нефига. На моей системе кое-как держится fps от 55-60(i3) в редких случаях падает до 48, на более старых системах, например двухядерных fps падает до 20, а то и меньше при скроллинге этой карты. Я убирал эти 2000 объектов(одного размера) и оставлял 130 разного. Фпс естественно возрастает, но все равно на старой системе при движении фпс падает примерно до 35-40. Если не двигать ничего, то стабильно 60.

caseyryan
24.03.2016, 06:08
Атлас я так понимаю, это вектор битмап? А как это повлияет на производительность?

Это атлас текстур (http://bfy.tw/4uQQ)

Godwarlock
24.03.2016, 19:10
caseyryanОкей. Так как это повлияет на производительность? Тайлсет в одной битмапе, ведь тоже по сути можно считать атласом? Но за счет чего будет прирост?

faraday
24.03.2016, 20:52
если ты уже используешь тайлсет, то откуда появляются мувиклипы? на сцене одновременно не должно добавляться да и находится 2000 объектов. перерисовывай только вьювпорт

Godwarlock
24.03.2016, 22:24
Визуально, там где находится персонаж, добавлено около 200 объектов, остальные 1800 удаляются со сцены и добавляются, только тогда, когда они попадают в фокус. Тайлсет я не использую, но могу попробовать и чтобы начать, хотелось бы услышать ответ, чем это лучше обычных мувиклипов.

caseyryan
25.03.2016, 08:38
Вместо мувиклипов лучше использовать для обертки Sprite, он более легковесный, не имеет временной шкалы, которую нужно все время считать.
И второе, зачем у тебя создается 2000 новых объектов? Почему ты не используешь пул?

Godwarlock
25.03.2016, 17:56
Вместо мувиклипов лучше использовать для обертки Sprite
В одном мувиклипе 8 картинок, то есть 8 видов основной картинки. Если переделывать в спрайты их, это получается надо создавать 8 спрайтов на каждый вид. А если видов около 50 или больше? Это 400 спрайтов в библиотеке.
И второе, зачем у тебя создается 2000 новых объектов? Почему ты не используешь пул?
Добавляем 2000, но 80% удаляется со сцены и добавляются по необходимости. Это своего рода и есть пул.

p.s Чтобы убедиться, я перевел картинку из мувиклипа в спрайт и добавлял уже не мвк, а спрайт. Никакой производительности это не дало.

Добавлено через 2 часа 47 минут
Заметил такую фишку. В общем на сцене двигается персонаж, а не платформа, а чтобы следить за персонажем каждый кадр вызывается функция
viewMap.centerOnPt(ptPlayer, true);//as3isolib
То есть камера всегда смотрим в центр персонажа. Я убрал её и подвигался без слежения камеры. Фпс на старом ноуте таким образом сохраняется в пределах 50-60, то есть лагов практически не наблюдается. Отсюда вопрос, если не использовать выше указанную функцию, каким образом мне тогда двигать карту и персонажа? У сцены нет свойства x,y поэтому двигать её не получится, но можно двигать объекты который расположены на всей это сцене. Получается надо брать координаты каждого объекта(то есть все 2000) и смещать в нужную сторону?

dimarik
25.03.2016, 23:00
Всем привет. Создается к примеру 2000 объектов. Добавление объектов идет таким образом
var model:MovieClip = new (ApplicationDomain.currentDomain.getDefinition("object_" + id) as Class);//object_+id - это ссылка на экземпляр movieClip с картинкой.
addChild(model);
Скажите чем плох таков вариант, если подобных объектов очень много добавляется на сцену? Подскажите другие варианты реализации, более оптимизированные, если таково надо.

Взгляд зацепился за название переменной "model". Обычно так называют модель данных, но не визуалки.
А вариант очень хороший. Он хорош тем, что вы не должны вкомпиливать все классы ваших 2000 объектов.
Ну, можно заменить на
getDefinitionByName("object_" + id);


каким образом мне тогда двигать карту и персонажа? У сцены нет свойства x,y поэтому двигать её не получится, но можно двигать объекты который расположены на всей это сцене. Получается надо брать координаты каждого объекта(то есть все 2000) и смещать в нужную сторону?
Нет, конечно, всех двигать по отдельности не нужно. Это чревато потерей производительности. Всех очень хорошо двигает контейнер, в котором "все" находятся. Двигайте контейнер. А все его дети двигаются чисто математически через матрицы трансформации. Математика работает быстро. Это и есть "камера". Вы можете её сделать без as3isolib.

Godwarlock
25.03.2016, 23:07
dimarik Да это понятно) Еще бы разобраться с оптимизацией работы со всеми этими объектами)

dimarik
25.03.2016, 23:16
Задавайте вопросы и будем разбираться.

Godwarlock
25.03.2016, 23:53
dimarik да я тут на две страницы уже раскочегарился)
Ну давайте попробуем поподробнее разобраться в моей проблеме)
В общем есть класс объекта, в который передаются нужные параметры, x,y,z, контейнер в который помещаем объект и т.д.


id = i;
type = t;
sorting = s;
setX = x;
setY = y;
setZ = z;
setR = r;
thisContainer - это обычный IsoDisplayObject

model = new (ApplicationDomain.currentDomain.getDefinition("platform_" + id) as Class);
model.gotoAndStop(setR);
model.cacheAsBitmap = true;
objectModel = new IsoDisplayObject();
objectModel.moveTo(setX, setY, setZ);
objectModel.container.addChild(model);
thisContainer.addChild(objectModel);
thisContainer.container.mouseChildren = false;
thisContainer.container.mouseEnabled = false;

//Эта функция вызывается, если объект попадает в область видимости.
public function addObject():void
{
if (flagVisible)
{
flagVisible = false;
thisContainer.addChild(objectModel);

}
}

//Эта функция вызывается, если объект вне зоны видимости.
public function deleteObject():void
{
if (!flagVisible)
{
flagVisible = true;
thisContainer.removeChild(objectModel);
}
}
Из всевозможных способов(visible,alpha и т.д) лучше всего проявил себя addChild и removeChild, другие варианты жрут fps больше всего.

Всё. Тут мы добавили объект и сам класс объекта кидаем в вектор. И таких вот объектов создается 2000+. И даже если оставить из 2000, только декорации, коих 140шт, фпс все равно проседает на ноуте до 30-40.
Далее, в контроллере управления персонажем, вызывается по энтерфейму функция, которая определяет какие объекты вне зоны, относительно персонажа. То есть пробегаемся по вектору с этими объектами и меняем его состояние видимости/невидимости, вызывая выше перечисленные функции удаления/добавления объектов для каждого экземпляра в массиве. Вызывать эту функцию только при движении персонажа или каждый кадр, не влияет ни на что. Проверено.

private function updatePlayerCoordinates(e:Event):void
{
ptPlayer = new Pt(WorldConfigurations.cameraObject.x, WorldConfigurations.cameraObject.y);//Здесь получаем координаты персонажа, относительно изометрической сетки. WorldConfigurations.cameraObject - это ссылка на активный объект. В игре есть кинематика, когда вместо игрока перемещается например квестовый нпс и поэтому чтобы карта следовала за ним, мы берем координаты именно из этой переменной.
viewMap.centerOnPt(ptPlayer, true);//Эта функция, которая центрирует камеру вьюшки относительно текущих координат персонажа
updateMap();//Эта функция, которая как раз проверяет какие объекты в зоне видимости, а какие вне зоны.
Вот пример зажатой кнопки W(вверх), по которой изменяем координаты персонажа когда он двигается вверх. (персонаж двигается в 8 направлениях)
if (up_press_platform)
{
thisX = playerObject.sprite.x -= UserConf.speed;
thisY = playerObject.sprite.y -= UserConf.speed;
playerObject.updateRotation(5);
}
}
updatePlayerXY(thisX, thisY);//Присваиваем объекту новые координаты, если не было столкновений и прочего в условиях

private function updatePlayerXY(x:int, y:int):void
{

playerObject.sprite.x = x;
playerObject.sprite.y = y;

}

Всё вроде бы нормально. На моём i3 fps держится в пределах 55-60, в редких случаях до 48 опускается. На двухядерных процах, при таком раскладе fps падает до 20, а то и меньше. Если убрать
viewMap.centerOnPt(ptPlayer, true); эту функцию, карта не будет следовать за текущим объектом, персонаж двигается, фпс на старом железе при этом держится в пределах 50-60, это в прочем нормально. Я был бы рад даже такому результату, если бы еще и карта двигалась) Как оказалось, смещение карты без функции центрирования камеры также не дало результатов, фпс проседать стал ровно также, как и с этой функцией. Собственно, оптимизировать нефига не получилось и вообще уже начинаю сомневаться, что сохранить стабильный фпс с большими картами на двухядерных процах текущие версии flash player-а не в состоянии...

dimarik
26.03.2016, 00:44
Всё. Тут мы добавили объект и сам класс объекта кидаем в вектор. И таких вот объектов создается 2000+. И даже если оставить из 2000, только декорации, коих 140шт, фпс все равно проседает на ноуте до 30-40.

Ну, кидаете в вектор вы, скорее всего не класс, а тот же самый объект (экземпляр класса), это должно быть очевидно. Очень неграмотно звучит.

Ставьте cacheAsBitmap у этих мувиклипов. Они изначально векторные. Но есть известные ограничения. Прочитайте про cacheAsBitmap.

пробегаемся по вектору с этими объектами и меняем его состояние видимости/невидимости, вызывая выше перечисленные функции удаления/добавления объектов для каждого экземпляра в массиве. Вызывать эту функцию только при движении персонажа или каждый кадр, не влияет ни на что. Проверено.

Удаление объекта из памяти влечет за собой срабатывание garbage collector. Этот процесс занимает серьёзное количество времени.
Добавление (создание) объекта зановно тоже отнимает время. Выделение памяти средствами ОС и все такое. Причем визуально это тот же самый объект.

Чтобы не рендерить визуальный объект воспользуйтесь его свойствами и выставьте: alpha = 0.0 или visible = false. Различие только в хиттесте для Mouse. Не удаляйте через removeChild. Вызов любого метода сам по себе накладен. Вам же нужно следить за тем, чтобы количество объектов не превысило условную величину.
Ну, я к тому, что иногда все-таки нужно удалять "лишние" объекты из памяти. Я очень четко это понял, когда работал с мобилками. Нам OS выделяла 256 Мб памяти или благополучно нас выгружала, если мы превышали эту квоту.

Проверьте ваше приложение через профилировщик Adobe Scout. Этот инструмент должен стать обыденностью для вас.

Godwarlock
26.03.2016, 01:21
Ставьте cacheAsBitmap у этих мувиклипов. Они изначально векторные. Но есть известные ограничения. Прочитайте про cacheAsBitmap.
model = new (ApplicationDomain.currentDomain.getDefinition("platform_" + id) as Class);
model.gotoAndStop(setR);
model.cacheAsBitmap = true;
В этих строка указывается cacheAsBitmap
Чтобы не рендерить визуальный объект воспользуйтесь его свойствами и выставьте: alpha = 0.0 или visible = false
Выставлял. При visible false у меня на системе fps проседает до 50, при removeChild держится до 60, тоже самое касается alpha.
я к тому, что иногда все-таки нужно удалять "лишние" объекты из памяти. Я очень четко это понял, когда работал с мобилками. Нам OS выделяла 256 Мб памяти или благополучно нас выгружала, если мы превышали эту квоту.
Несмотря на размеры игровой карты, игрового интерфейса и прочего, приложение потребляет всего 70мб памяти)
Проверьте ваше приложение через профилировщик Adobe Scout. Этот инструмент должен стать обыденностью для вас.
Да я бы с радостью, я так понял это что-то вроде дебаггера в Java. Но увы, скачал этот скаут, но он не видит запущенных swf приложений. Попробую конечно другой скачать, но фиг знает.

dimarik
26.03.2016, 01:35
Соррян, не заметил про уже установленный cacheAsBitmap. Однако его установка может вызвать падение производительности. Проверьте, что это не ваш случай. Насколько помогло или, наоборот, усугубило установка этого флага?

Ну скиньте сюда или в личку сслыль на тестовый пример, я постараюсь помочь наживую.

Godwarlock
26.03.2016, 03:15
Соррян, не заметил про уже установленный cacheAsBitmap. Однако его установка может вызвать падение производительности. Проверьте, что это не ваш случай. Насколько помогло или, наоборот, усугубило установка этого флага?
К моему счастью, cacheAsBitmap поднял фпс примерно на 5-10. Без него сильнее тормозило. Скинул проект в лс