set udg_Group = GetUnitsOfPlayerAll(Player(0))
Вот именно UnitsOfPlayer что-то создает и не удаляет, а мне это очень нужно чтобы выбирать юнитов с москитами, а триггеров в карте с их созданием оочень много и везде добавлять их в группу не варик
Триггер периодик, за 3 использования уже лагать начинает, поэтому надо убрать утечки

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

Ну, Варкрафт 3 в целом не любит когда слишком много юнитов одновременно на экране, а если учитывать, что у них ещё возможно есть и модель, то графическая часть начинает сильно резать фпс, с этим особо ты ничего не сделаешь. По поводу твоего кода, слишком напоминает GUI особенно проверками, ниже как бы я написал, но так как это отрывок и нет пояснения что в целом код должен делать, то я не знаю сколь близко он выполнит твои цели/нужды.
Код
globals
    timer gg_timer_Move = null
endglobals

function GetAxisAngle takes real fromX, real fromY, real targX, real targY returns real
	return Rad2Deg( Atan2( targY - fromY, targX - fromX ) )
endfunction

function GetAxisDistance takes real castX, real fcastY, real targX, real targY returns real
	return SquareRoot( Pow( targX - castX, 2 ) + Pow( fcastY - targY, 2 ) )
endfunction

function NewX takes real locX, real dist, real angle returns real
	return locX + dist * Cos( Deg2Rad( angle ) )
endfunction

function NewY takes real locY, real dist, real angle returns real
	return locY + dist * Sin( Deg2Rad( angle ) )
endfunction

function Move_GroupActionsHandler takes unit target returns nothing
    local integer uid   = GetUnitTypeId( target )
    local real speed    = 8   //скорость движения | Локальные переменные советую писать с маленькой буквы.
    local real targX    = GetUnitX( target ) // GetWidgetX не быстрее GetUnitX, не нужно этого делать :)
    local real targY    = GetUnitY( target ) // GetWidgetY не быстрее GetUnitY, не нужно этого делать :)
    local real moveX    = 0.
    local real moveY    = 0.
    local real angle    = 0.

    if udg_Time >= 6000 then
        if uid >= 'h044' and uid <= 'h046' then
            call RemoveUnit( target )
        else
            call UnitDamageTargetBJ( udg_Caster, target, 2000., ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNKNOWN )
        endif
    else
        if GetAxisDistance( udg_CasterX, udg_CasterY, targX, targY ) <= udg_Time / 10 * 8 then // Сделай один раз враппер и будет проще.
            if RAbsBJ( targX ) <= 4000 and RAbsBJ( targY ) <= 4000 then    //чтобы не двигал если юнит на краю карты | не нужно каждый раз читать местоположение по-новой.
                if not IsUnitType( target, UNIT_TYPE_STRUCTURE ) and target != udg_Caster and target != udg_DummyCaster then
                    set angle = GetAxisAngle( udg_CasterX, udg_CasterY, targX, targY ) //угол между координатами кастера и коорд юнита | через враппер.
                    set moveX = NewX( moveX, speed, angle )
                    set moveY = NewY( moveY, speed, angle ) // В твоей же системе было с минусом, ибо угол считался от кастера, собственно, если нужно отталкивание, но нужен +, если что просто замени на -speed

                    if not IsTerrainPathable( moveX, moveY, PATHING_TYPE_FLYABILITY ) or uid == 'h045' or uid == 'h046' then // лучше в начале проверить есть ли смысл двигать или нет.
                        // + RAbsBJ( 50 ) дал бы не совсем правильные результаты, ибо координаты могут быть отрицательными...
                        if GetTerrainType( moveX, moveY ) != 'Jdrt'  then
                            call SetTerrainType( moveX, moveY, 'Jdrt', -1, 1, 0 )       //если тип земли не изменен на этот, изменить его
                        endif
                        call SetUnitX( target, moveX )  //двигаем юнита
                        call SetUnitY( target, moveY )
                    endif
                endif
            endif
        endif
    endif
endfunction

function Move_GroupActions takes nothing returns nothing  //двигаем всех юнитов от точки кастера??
    call Move_GroupActionsHandler( GetEnumUnit( ) )
endfunction

function Move_Actions takes nothing returns nothing
    local integer i = 0
    local integer pid = GetOwningPlayer( udg_Caster )

    if udg_Time == 0 then  //в начале создаются даммики 45 штук...
        loop
            exitwhen i == 45
            set udg_MoveAngle = i * 8.
            set udg_Dummy[ i ] = CreateUnit( Player( pid ), 'h045', udg_CasterX - 200 * Cos( udg_MoveAngle ), udg_CasterY - 200 * Sin( udg_MoveAngle ), udg_MoveAngle )
            set i = i + 1
        endloop

        if udg_Group == null then
            set udg_Group = CreateGroup( )
        endif
    else
        if udg_Time <= 6000 then
            set i = 0
            loop
                exitwhen i > bj_MAX_PLAYERS // цикл всех игроков ничем не хуже...
                if Player( i ) == PLAYER_SLOT_STATE_PLAYING then
                    call GroupEnumUnitsOfPlayer( udg_Group, Player( i ), null )
                    call ForGroup( udg_Group, function Move_GroupActions )
                    call GroupClear( udg_Group )
                endif
                set i = i + 1
            endloop
        else
            call PauseUnit( udg_Caster, false )
            call PauseTimer( gg_timer_Move )
        endif
    endif

    set udg_Time = udg_Time + 10
endfunction

//===========================================================================
function InitTrig_Move takes nothing returns nothing
    set gg_timer_Move = CreateTimer( )
    call TimerStart( gg_timer_Move, .01, true, function Move_Actions )
endfunction
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
19
4 года назад
0
Похожие вопросы:

ответ
Причина: причин было много, а я искал лишь одну
Самыми распространёнными оказались элементарные ошибки в коде, отсутствие параметров, параметры не того типа данных (привет динамическая типизация) или лишние параметры, из за чего происходили "рандомные рассинхроны при обрыве потока"
Огромное спасибо пользователю prog, что откликнулся и смог найти ошибки, а нашёл он их при помощи языкового сервера sumneko lua для VScode

0
1
4 года назад
Отредактирован Undert4ker
0
Лаги происходят из-за множественного перебора всех юнитов игрока, в том случае, если их довольно много. Соответственно, чем больше юнитов перебирает, тем больше нагрузка на движок. К тому же, предлагаю следующий вид для перебора юнитов в группе:
ТЫК
Если нужно только для конкретного игрока, цикл можно не использовать...
set bj_lastCreatedGroup = CreateGroup()
loop
exitwhen i == bj_MAX_PLAYER_SLOTS
call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup,Player(i),null)
call ForGroup(bj_lastCreatedGroup,function Filter)
set i = i + 1
endloop
call GroupClear(bj_lastCreatedGroup)
call DestroyGtoup(bj_lastCreatedGroup)
0
22
4 года назад
0
как вариант, в конце каждого тика таймера:
call DestroyGroup(udg_Group)
Загруженные файлы
0
23
4 года назад
0
Удалять надо лол. Статьи плохо наверное читали.
0
32
4 года назад
0
Страшны не как сам утечки, а как количество юнитов в переборе

Продебаж количество вызовов, а конкретно количество юнитов при каждом переборе
0
10
4 года назад
Отредактирован Lotus101
0

цитата
как вариант, в конце каждого тика таймера:
call DestroyGroup(udg_Group)
pro100master:
Удалять надо лол. Статьи плохо наверное читали.
Итак удаляю, все что с группой связано
Bergi_Bear:
цитата
Страшны не как сам утечки, а как количество юнитов в переборе

Продебаж количество вызовов, а конкретно количество юнитов при каждом переборе
Даже если указываю игрока, которого нет в карте, все равно есть утечка


Вообщем дело было в чертовом гуишном "Юниты игрока/юниты игрока типа/юнита игрока при условии/юниты игрока в области" в любом случае создавал утечку, и как удалять не знаю
set udg_Group = GetUnitsOfPlayerAll(GetEnumPlayer())
но если писать вручную:
call GroupEnumUnitsOfPlayer( udg_Group, GetEnumPlayer(), null)
то все работает отлично.
Так что лучше это PlayerAll не использовать. Всем спасибо.


Осталось придумать как оптимизировать чтобы не провисало и проц не дымился при таком переборе, если юнитов на карте мало, то все нормально, если более 100 + даммики создаются, то начинаются проблемы... (а перед этой функцией еще спамятся даммики...) Есть идеи?
вот этот монстр
function Move_ConditTime10 takes nothing returns boolean
    if ( not ( udg_Time == 10 ) ) then
        return false
    endif
    return true
endfunction

function Move_ConditTypeDelete takes nothing returns boolean
    if ( ( GetUnitTypeId(GetEnumUnit()) == 'h044' ) ) then
        return true
    endif
    if ( ( GetUnitTypeId(GetEnumUnit()) == 'h045' ) ) then
        return true
    endif
    if ( ( GetUnitTypeId(GetEnumUnit()) == 'h046' ) ) then
        return true
    endif
    return false
endfunction

function Move_ConditDelete takes nothing returns boolean
    if ( not Move_ConditTypeDelete() ) then
        return false
    endif
    return true
endfunction

function Move_ConditTypeEnum takes nothing returns boolean
    if ( not ( IsUnitType(GetEnumUnit(), UNIT_TYPE_STRUCTURE) == false ) ) then
        return false
    endif
    if ( not ( GetEnumUnit() != udg_Caster ) ) then
        return false
    endif
    if ( not ( GetEnumUnit() != udg_DummyCaster ) ) then
        return false
    endif
    return true
endfunction

function Move_ConditTime6000 takes nothing returns boolean
    if ( not ( udg_Time >= 6000 ) ) then
        return false
    endif
    return true
endfunction

function Move_GroupActions takes nothing returns nothing   ??//двигаем всех юнитов от точки кастера??
    local real Speed = 8   //скорость движения                                                 //снизу проверяем минимальное расстояние от выбранного юнита до точки кастера + Time
    if SquareRoot((GetWidgetX(GetEnumUnit()) - udg_CasterX) * (GetWidgetX(GetEnumUnit()) - udg_CasterX) + (GetWidgetY(GetEnumUnit()) - udg_CasterY) * (GetWidgetY(GetEnumUnit()) - udg_CasterY)) <= udg_Time/10*8  then 
    if RAbsBJ(GetWidgetX(GetEnumUnit())) <= 4000 and RAbsBJ(GetWidgetY(GetEnumUnit())) <= 4000 then    //чтобы не двигал если юнит на краю карты
    if ( Move_ConditTime6000() ) then       //выключение триггера спустя 6 секунд
        if ( Move_ConditDelete() ) then
            call RemoveUnit( GetEnumUnit() )
        else
            call UnitDamageTargetBJ( udg_Caster, GetEnumUnit(), 2000.00, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNKNOWN )
        endif
        call PauseUnitBJ( false, udg_Caster )
        call DisableTrigger( GetTriggeringTrigger() )
    else
        if ( Move_ConditTypeEnum() ) then
            set udg_MoveAngle = Atan2(udg_CasterY-GetWidgetY(GetEnumUnit()), udg_CasterX-GetWidgetX(GetEnumUnit()))    //угол между координатами кастера и коорд юнита
            set udg_MoveX = GetWidgetX(GetEnumUnit())-Speed*Cos(udg_MoveAngle)  //X куда двигать юнита??
            set udg_MoveY = GetWidgetY(GetEnumUnit())-Speed*Sin(udg_MoveAngle)  //Y куда двигать юнита??
            if GetTerrainType(udg_MoveX, udg_MoveY) != 'Jdrt'  then
            call SetTerrainType( udg_MoveX, udg_MoveY, 'Jdrt', -1, 1, 0 )       //если тип земли не изменен на этот, изменить его
            endif                                                              //снизу проверяем проходима ли местность для юнита чтобы двигать
            if IsTerrainPathable(udg_MoveX+RAbsBJ(50), udg_MoveY+RAbsBJ(50), PATHING_TYPE_FLYABILITY) == false or GetUnitTypeId(GetEnumUnit()) == 'h045' or GetUnitTypeId(GetEnumUnit()) == 'h046' then
            call UnitDamageTargetBJ( udg_Caster, GetEnumUnit(), 3.00, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNKNOWN )
            call SetUnitX(GetEnumUnit(), udg_MoveX)  //двигаем юнита
            call SetUnitY(GetEnumUnit(), udg_MoveY)
            endif
        else
        endif
    endif
    endif
    endif
endfunction

function MoveGetEnum takes nothing returns nothing  //для каждого игрока выбираем всех его юнитов
    set udg_Group = CreateGroup()   //каждый раз создаем группу(надо ли?)
    set bj_wantDestroyGroup = true   //скрипт на автоудаление группы(надо ли?)
    call GroupEnumUnitsOfPlayer( udg_Group, GetEnumPlayer(), null)  //выбираем группу
    call ForGroupBJ( udg_Group, function Move_GroupActions )
    call GroupClear( udg_Group )  //очищаем группу(надо ли?)
    call DestroyGroup(udg_Group)  //удаляем группу(?)
    set udg_Group = null    ??//переменная группы равна 0(?, вроде и без этого всего не было утечек, но навсякий)
endfunction

function Move_Actions takes nothing returns nothing
    set udg_Time = ( udg_Time + 10 )
    if ( Move_ConditTime10() ) then  //в начале создаются даммики 45 штук...
        set bj_forLoopAIndex = 1
        set bj_forLoopAIndexEnd = 45
        loop
            exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd
            set udg_MoveAngle = ( I2R(GetForLoopIndexA()) * 8.00 )
            set udg_MoveX = udg_CasterX-200*Cos(udg_MoveAngle)
            set udg_MoveY = udg_CasterY-200*Sin(udg_MoveAngle)
            set udg_Dummy[GetForLoopIndexA()] = CreateUnit(GetOwningPlayer(udg_Caster), 'h045', udg_MoveX, udg_MoveY, ( I2R(GetForLoopIndexA()) * 8.00 ))
            set bj_forLoopAIndex = bj_forLoopAIndex + 1
        endloop
    else
    endif
    call ForForce( GetPlayersAll(), function Move_GetEnum )  //выбор каждого игрока
endfunction

//===========================================================================
function InitTrig_Move takes nothing returns nothing
    set gg_trg_Move = CreateTrigger(  )
    call DisableTrigger( gg_trg_Move )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Move, 0.01 )
    call TriggerAddAction( gg_trg_Move, function Move_Actions )
endfunction
2
20
4 года назад
2
Ну, Варкрафт 3 в целом не любит когда слишком много юнитов одновременно на экране, а если учитывать, что у них ещё возможно есть и модель, то графическая часть начинает сильно резать фпс, с этим особо ты ничего не сделаешь. По поводу твоего кода, слишком напоминает GUI особенно проверками, ниже как бы я написал, но так как это отрывок и нет пояснения что в целом код должен делать, то я не знаю сколь близко он выполнит твои цели/нужды.
Код
globals
    timer gg_timer_Move = null
endglobals

function GetAxisAngle takes real fromX, real fromY, real targX, real targY returns real
	return Rad2Deg( Atan2( targY - fromY, targX - fromX ) )
endfunction

function GetAxisDistance takes real castX, real fcastY, real targX, real targY returns real
	return SquareRoot( Pow( targX - castX, 2 ) + Pow( fcastY - targY, 2 ) )
endfunction

function NewX takes real locX, real dist, real angle returns real
	return locX + dist * Cos( Deg2Rad( angle ) )
endfunction

function NewY takes real locY, real dist, real angle returns real
	return locY + dist * Sin( Deg2Rad( angle ) )
endfunction

function Move_GroupActionsHandler takes unit target returns nothing
    local integer uid   = GetUnitTypeId( target )
    local real speed    = 8   //скорость движения | Локальные переменные советую писать с маленькой буквы.
    local real targX    = GetUnitX( target ) // GetWidgetX не быстрее GetUnitX, не нужно этого делать :)
    local real targY    = GetUnitY( target ) // GetWidgetY не быстрее GetUnitY, не нужно этого делать :)
    local real moveX    = 0.
    local real moveY    = 0.
    local real angle    = 0.

    if udg_Time >= 6000 then
        if uid >= 'h044' and uid <= 'h046' then
            call RemoveUnit( target )
        else
            call UnitDamageTargetBJ( udg_Caster, target, 2000., ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNKNOWN )
        endif
    else
        if GetAxisDistance( udg_CasterX, udg_CasterY, targX, targY ) <= udg_Time / 10 * 8 then // Сделай один раз враппер и будет проще.
            if RAbsBJ( targX ) <= 4000 and RAbsBJ( targY ) <= 4000 then    //чтобы не двигал если юнит на краю карты | не нужно каждый раз читать местоположение по-новой.
                if not IsUnitType( target, UNIT_TYPE_STRUCTURE ) and target != udg_Caster and target != udg_DummyCaster then
                    set angle = GetAxisAngle( udg_CasterX, udg_CasterY, targX, targY ) //угол между координатами кастера и коорд юнита | через враппер.
                    set moveX = NewX( moveX, speed, angle )
                    set moveY = NewY( moveY, speed, angle ) // В твоей же системе было с минусом, ибо угол считался от кастера, собственно, если нужно отталкивание, но нужен +, если что просто замени на -speed

                    if not IsTerrainPathable( moveX, moveY, PATHING_TYPE_FLYABILITY ) or uid == 'h045' or uid == 'h046' then // лучше в начале проверить есть ли смысл двигать или нет.
                        // + RAbsBJ( 50 ) дал бы не совсем правильные результаты, ибо координаты могут быть отрицательными...
                        if GetTerrainType( moveX, moveY ) != 'Jdrt'  then
                            call SetTerrainType( moveX, moveY, 'Jdrt', -1, 1, 0 )       //если тип земли не изменен на этот, изменить его
                        endif
                        call SetUnitX( target, moveX )  //двигаем юнита
                        call SetUnitY( target, moveY )
                    endif
                endif
            endif
        endif
    endif
endfunction

function Move_GroupActions takes nothing returns nothing  //двигаем всех юнитов от точки кастера??
    call Move_GroupActionsHandler( GetEnumUnit( ) )
endfunction

function Move_Actions takes nothing returns nothing
    local integer i = 0
    local integer pid = GetOwningPlayer( udg_Caster )

    if udg_Time == 0 then  //в начале создаются даммики 45 штук...
        loop
            exitwhen i == 45
            set udg_MoveAngle = i * 8.
            set udg_Dummy[ i ] = CreateUnit( Player( pid ), 'h045', udg_CasterX - 200 * Cos( udg_MoveAngle ), udg_CasterY - 200 * Sin( udg_MoveAngle ), udg_MoveAngle )
            set i = i + 1
        endloop

        if udg_Group == null then
            set udg_Group = CreateGroup( )
        endif
    else
        if udg_Time <= 6000 then
            set i = 0
            loop
                exitwhen i > bj_MAX_PLAYERS // цикл всех игроков ничем не хуже...
                if Player( i ) == PLAYER_SLOT_STATE_PLAYING then
                    call GroupEnumUnitsOfPlayer( udg_Group, Player( i ), null )
                    call ForGroup( udg_Group, function Move_GroupActions )
                    call GroupClear( udg_Group )
                endif
                set i = i + 1
            endloop
        else
            call PauseUnit( udg_Caster, false )
            call PauseTimer( gg_timer_Move )
        endif
    endif

    set udg_Time = udg_Time + 10
endfunction

//===========================================================================
function InitTrig_Move takes nothing returns nothing
    set gg_timer_Move = CreateTimer( )
    call TimerStart( gg_timer_Move, .01, true, function Move_Actions )
endfunction
Принятый ответ
Чтобы оставить комментарий, пожалуйста, войдите на сайт.