Делаю одну большую карту на Warcraft 3 и столкнулся с проблемой утечек - почти стабильный краш примерно на 2 часу игры. Всё делаю (только не бейте) на обычном GUI, как я понял из поиска в интернете - это проблема с утечками, и скорее всего с точками создания юнитов.
Собственно, суть вопроса.
Избавлюсь ли я от утечек с точками, если будут перед каждым спавном иметь какую то переменную точки (назовём её P) и юнит будет создаваться не в "Область 019", а в "P", которая всегда меняется.
Избавлюсь ли я от утечек юнитов, если спустя n-минут после смерти труп удаляется действием "Боевая единица - Удалить".
Избавлюсь ли я от утечек спецэффектов, если аналогично юнитам, спецэффекты (и плавающий текст) удаляются спустя n-минут?
Нужно ли добавить к этому всему что то ещё?
Пы.сы. те статьи от бота я уже посмотрел, но не нашёл того, чего хотел

Принятый ответ

Надо, конечно, взглянуть на триггеры в карте, но при спавне удалять нужно не только точки, но и группы, так как при спавне создаются не только юниты, но и группа для них (даже из одного юнита группы). Без утечек создание юнитов выглядит так:
вот код для custom script:
call DestroyGroup( GetLastCreatedGroup() )
call RemoveLocation( udg_P )
Если отдаёшь приказ группе юнитов отправиться в область, там тоже создаётся группа и точка, тоже нужны эти custom script. Но вообще сомнительно, что это вызывает дикие лаги через два часа. Наверное, есть какие-то события с малым периодом, что тоже плодят утечки, поэтому и надо триггеры в карте смотреть.
Загруженные файлы
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
1
7
5 лет назад
1
Помогут статьи:
  1. Оптимизация - тык
  2. Оптимизация: утечки памяти - тык
Также по утечкам овер-много вопросов, так что по каждому случаю найдешь уже похожий вопрос->ответ.
Плюс, небольшой наглядный пример из пака наработок по их устранению.
Загруженные файлы
2
27
5 лет назад
Отредактирован MpW
2
по идее юнита не нужно удалять вручную (это то что написано в статье). он сам удалиться. и из группы удалиться тоже. игра сама удаляет. был тут анимешник по наруто, где везде пихал удаление после смерти. в каждом триггере (надо было просто один триггер на все сделать для удобства, группировать в ро удаляемых юнитов единой классификацией ). потом удивлялся, почему у него герой не воскрешается, а удаляется из игры (надо правильно пользоваться триггерами, условиями). карта у него лагала катастрофически из-за множества моделек видимо. это даймиков можно. хотя даймикам можно таймер смерти нацепить

подумайте об минусах мгновенного удаления: так вы не получаете трупов для некоторых заклинаний воскрешения и некромантии.

оптимизация нужна в том случае, если создал объект вроде таймера. сделал таймер свое дело, удалил - все
0
26
5 лет назад
0
Надо, конечно, взглянуть на триггеры в карте, но при спавне удалять нужно не только точки, но и группы, так как при спавне создаются не только юниты, но и группа для них (даже из одного юнита группы). Без утечек создание юнитов выглядит так:
вот код для custom script:
call DestroyGroup( GetLastCreatedGroup() )
call RemoveLocation( udg_P )
Если отдаёшь приказ группе юнитов отправиться в область, там тоже создаётся группа и точка, тоже нужны эти custom script. Но вообще сомнительно, что это вызывает дикие лаги через два часа. Наверное, есть какие-то события с малым периодом, что тоже плодят утечки, поэтому и надо триггеры в карте смотреть.
Загруженные файлы
Принятый ответ
0
7
5 лет назад
0
Steal nerves:
по идее юнита не нужно удалять вручную (это то что написано в статье). он сам удалиться. и из группы удалиться тоже. игра сама удаляет. был тут анимешник по наруто, где везде пихал удаление после смерти. в каждом триггере (надо было просто один триггер на все сделать для удобства, группировать в ро удаляемых юнитов единой классификацией ). потом удивлялся, почему у него герой не воскрешается, а удаляется из игры (надо правильно пользоваться триггерами, условиями). карта у него лагала катастрофически из-за множества моделек видимо. это даймиков можно. хотя даймикам можно таймер смерти нацепить

подумайте об минусах мгновенного удаления: так вы не получаете трупов для некоторых заклинаний воскрешения и некромантии.

оптимизация нужна в том случае, если создал объект вроде таймера. сделал таймер свое дело, удалил - все
у меня триггеры не мои были я учился просто копировал и т.д теперь знаю
кстати карта не лагает
0
9
5 лет назад
Отредактирован Lord_Tomat
0
Steal nerves:
по идее юнита не нужно удалять вручную (это то что написано в статье). он сам удалиться. и из группы удалиться тоже. игра сама удаляет. был тут анимешник по наруто, где везде пихал удаление после смерти. в каждом триггере (надо было просто один триггер на все сделать для удобства, группировать в ро удаляемых юнитов единой классификацией ). потом удивлялся, почему у него герой не воскрешается, а удаляется из игры (надо правильно пользоваться триггерами, условиями). карта у него лагала катастрофически из-за множества моделек видимо. это даймиков можно. хотя даймикам можно таймер смерти нацепить

подумайте об минусах мгновенного удаления: так вы не получаете трупов для некоторых заклинаний воскрешения и некромантии.

оптимизация нужна в том случае, если создал объект вроде таймера. сделал таймер свое дело, удалил - все
В карте трупы никак не используются, героев нету и воскрешение не продумано, меня это не волнует.
8gabriel8:
Надо, конечно, взглянуть на триггеры в карте, но при спавне удалять нужно не только точки, но и группы, так как при спавне создаются не только юниты, но и группа для них (даже из одного юнита группы). Без утечек создание юнитов выглядит так:
вот код для custom script:
call DestroyGroup( GetLastCreatedGroup() )
call RemoveLocation( udg_P )
Если отдаёшь приказ группе юнитов отправиться в область, там тоже создаётся группа и точка, тоже нужны эти custom script. Но вообще сомнительно, что это вызывает дикие лаги через два часа. Наверное, есть какие-то события с малым периодом, что тоже плодят утечки, поэтому и надо триггеры в карте смотреть.
Я думаю, это поможет, но тут ещё вопрос
Предметы считаются за юнита? Что насчёт "Заменённых" юнитов?
Пы.сы. в триггерах самый "частый" тригер - установка рандомного числа в переменную раз в 20 секунд, остальные идут от минуты до пяти
0
26
5 лет назад
0
Предмет - это своеобразный объект, как юнит или декорация, но не юнит. Заменённые юниты теоретически не должны утекать, но тут зависит от реализации, вдруг каждого юнита прогоняешь через глобальную переменную перед заменой, тогда утечки будут, но раз уж ты спросил о них, то лучше посмотреть.
P. S. Имею ввиду не обязательно время, но и вообще что-то частое. Например, при каждой атаке создаётся эффект, который не удаляется.

Меня вообще мало волнуют утечки, так как занимаюсь кампаниями, а не мультиплеерными картами, просто наблатыкался с этим, так как много здесь сижу. Но вообще создали много разных триггеров для вывода количества утечек - счётчики хендлов. Поищи такой, поставь себе в карту и прикидывай, как меняется количество утечек в игре, когда проводишь чистку в триггерах, может в какие-то моменты особенно сильный рост утечек будет.
Там будет выводится число, которое показывает, что такое-то количество объектов хранится в памяти. По ходу игры счётчик будет немного расти и падать, что нормально. Если же счётчик по сути лишь растёт, значит надо убирать утечки. Идеально будет, если по ходу игры счётчик почти не будет меняться, но это задротство, не стремись к этому, просто знай, что стабильность - это хорошо.
Ещё не факт, что именно утечки вызывают фатал.
1
28
5 лет назад
1
По поводу групп: можно не удалять группу через Destroy Group, а перед вызовом (выбрать всех юнитов в группе и сделать то-то) написать в Custom Script
set bj_wantDestroyGroup = true
Тогда группа сама удалится.

Счётчикам особо доверять не стоит, но если что-то постоянно утекает, то они это заметят.
0
26
5 лет назад
0
Но это не работает с выбором всех юнитов определённого типа на карте.
0
28
5 лет назад
Отредактирован PT153
0
Но это не работает с выбором всех юнитов определённого типа на карте.
Pick every unit in group and do actions вызывает ForGroupBJ(), в которой при bj_wantDestroyGroup == true группа удаляется.
ForGroupBJ
function ForGroupBJ takes group whichGroup, code callback returns nothing
    // If the user wants the group destroyed, remember that fact and clear
    // the flag, in case it is used again in the callback.
    local boolean wantDestroy = bj_wantDestroyGroup
    set bj_wantDestroyGroup = false

    call ForGroup(whichGroup, callback)

    // If the user wants the group destroyed, do so now.
    if (wantDestroy) then
        call DestroyGroup(whichGroup)
    endif
endfunction
Не работает как раз-таки способ с удалением GetLastCreatedGroup(), потому что все BJ функции групп используют локалки.
Функции
function GetUnitsInRangeOfLocMatching takes real radius, location whichLocation, boolexpr filter returns group
    local group g = CreateGroup()
    call GroupEnumUnitsInRangeOfLoc(g, whichLocation, radius, filter)
    call DestroyBoolExpr(filter)
    return g
endfunction

function GetUnitsInRectMatching takes rect r, boolexpr filter returns group
    local group g = CreateGroup()
    call GroupEnumUnitsInRect(g, r, filter)
    call DestroyBoolExpr(filter)
    return g
endfunction

function GetUnitsInRectOfPlayer takes rect r, player whichPlayer returns group
    local group g = CreateGroup()
    set bj_groupEnumOwningPlayer = whichPlayer
    call GroupEnumUnitsInRect(g, r, filterGetUnitsInRectOfPlayer)
    return g
endfunction

function GetUnitsOfPlayerAndTypeId takes player whichPlayer, integer unitid returns group
    local group g = CreateGroup()
    set bj_groupEnumTypeId = unitid
    call GroupEnumUnitsOfPlayer(g, whichPlayer, filterGetUnitsOfPlayerAndTypeId)
    return g
endfunction

function GetUnitsOfPlayerMatching takes player whichPlayer, boolexpr filter returns group
    local group g = CreateGroup()
    call GroupEnumUnitsOfPlayer(g, whichPlayer, filter)
    call DestroyBoolExpr(filter)
    return g
endfunction

function GetUnitsOfTypeIdAll takes integer unitid returns group
    local group   result = CreateGroup()
    local group   g      = CreateGroup()
    local integer index

    set index = 0
    loop
        set bj_groupEnumTypeId = unitid
        call GroupClear(g)
        call GroupEnumUnitsOfPlayer(g, Player(index), filterGetUnitsOfTypeIdAll)
        call GroupAddGroup(g, result)

        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop
    call DestroyGroup(g)

    return result
endfunction

function GetUnitsSelectedAll takes player whichPlayer returns group
    local group g = CreateGroup()
    call SyncSelections()
    call GroupEnumUnitsSelected(g, whichPlayer, null)
    return g
endfunction
Так что самый верный способ будет через присвоение.
set bj_wantDestroyGroup = true

Локации удалять через RemoveLocation(), а группы через set bj_wantDestroyGroup = true.
0
26
5 лет назад
0
Обработает лишь красного игрока и удалит группу, а у остальных игроков юнитов нужного типа неоткуда будет брать.
PT153:
Не работает как раз-таки способ с удалением GetLastCreatedGroup(), потому что все BJ функции групп используют локалки.
Так это что получается, нужно сначала присвоить глобальную переменную локальной группе, чтобы потом её удалить?
0
28
5 лет назад
Отредактирован PT153
0
Обработает лишь красного игрока и удалит группу, а у остальных игроков юнитов нужного типа неоткуда будет брать.
Это было проверено на практике или нет?
Потому что по коду я вижу, что всё будет работать верно. Сначала сработает GetUnitsOfTypeIdAll(), и только потом ForGroupBJ(). Их код я кинул выше.
Если сконвертировать, то будет следующее.
call ForGroupBJ( GetUnitsOfTypeIdAll('hfoo'), function Trig_Untitled_Trigger_001_Func001A )
Это сработает так, как я сказал выше, потому что в JASS, как и во многих языках, передача по значению.

Так это что получается, нужно сначала присвоить глобальную переменную локальной группе, чтобы потом её удалить?
Нет, наоборот. Делаем переменную типа группа, в неё записываем нужную группу, после для неё вызываем Pick every unit in group and do actions, а затем удаляем. Это 3 строчки. Но зачем это, когда можно перед Pick every unit in group and do actions просто написать set bj_wantDestroyGroup = true с таким же результатом? И займет это 2 строчки.
Но это не работает с выбором всех юнитов определённого типа на карте.
Как я уже описал выше, работает, для практической проверки стоит посмотреть карту Лазурные башни, триггер Tech\Zenith Refresh.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.