XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Академия: форум для вопросов> Jass
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

Ответ
 
Fromitt

offline
Опыт: 445
Активность:
Проблемы с утечками
Заклинание посылает зеленую соплю в заданную точку. При полете снаряд ищет цель, в которую кидает shadowstrike.
Способность на редкость сильно грузит карту. Уже после сотого каста фпс падают до 20.
Даже мои гуи-поделки пятилетней давности, когда об оптимизации я ничего не знал, вызывали меньше лагов.
» Library UnitLib

Код:
library UnitLib
globals 
 unit array Unit
 real array unitX 
 real array unitY
 real array unitZ
 real array unitDis
 real array unitDir
 integer unitMaxIndex = 0
 integer unitUnusedAmount = 0
 integer array unitUnusedIndex
 boolean array unitTaken
 player array unitOwner
endglobals

function Distance takes real x1, real y1, real x2, real y2 returns real
    return SquareRoot((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
endfunction

function SetUnitZ takes unit u, real z returns nothing
    local location l = Location (0.00, 0.00)
    call MoveLocation (l, GetUnitX (u), GetUnitY (u))
    call SetUnitFlyHeight (u, z - GetLocationZ (l), 0.00)
    call RemoveLocation (l)
    set l = null
endfunction

function UnitCreate takes player p, integer m, real x, real y, real z, real dir, real dis returns nothing
    local integer i = 0
    if unitUnusedAmount == 0 then
        set unitMaxIndex = unitMaxIndex + 1
        set i = unitMaxIndex
    else
        set i = unitUnusedIndex[unitUnusedAmount]
        set unitUnusedIndex[unitUnusedAmount] = 0
        set unitUnusedAmount = unitUnusedAmount - 1
    endif
    set unitOwner[i] = p
    set Unit[i] = CreateUnit (p, m, x, y, 0)
    call UnitAddAbility (Unit[i],'Amrf')
    call UnitRemoveAbility (Unit[i],'Amrf')
    call SetUnitFacing (Unit[1], dir/0.0174)
    call SetUnitZ (Unit[i], z)
    set unitX[i] = x
    set unitY[i] = y
    set unitZ[i] = z
    set unitDir[i] = dir
    set unitDis[i] = dis
    set unitTaken[i] = true
endfunction

function UnitKill takes integer i returns nothing
    if unitTaken[i] then
      set unitTaken[i] = false
      set unitUnusedAmount = unitUnusedAmount + 1
      set unitUnusedIndex[unitUnusedAmount] = i
      set unitOwner[i] = null
      set Unit[i] = null
    endif
endfunction
endlibrary


» Library Poison Sting

Код:
library PoisonSting uses UnitLib
globals
    private integer PSunitCurrent = 0
    private group g = CreateGroup()
    private timer unitTimer
    integer PSnumber = 0
endglobals

function PSEnemyFilter takes nothing returns boolean
    return IsUnitEnemy (GetFilterUnit(), unitOwner[PSunitCurrent]) and GetWidgetLife(GetFilterUnit()) > 0
endfunction

function PSEnemyGroup takes integer i returns nothing
    local unit u
    call GroupEnumUnitsInRange(g, GetUnitX(Unit[i]), GetUnitY(Unit[i]), 75, Condition (function PSEnemyFilter ))
    set u = FirstOfGroup (g)
    if   u != null  then
      call IssueTargetOrder ( Unit[i], "shadowstrike", u )
      call GroupRemoveUnit (g, u)
      call ShowUnit ( Unit[i], false )
      call UnitApplyTimedLife( Unit[i], 'BEfn', 0.2 )
     // call DisplayTimedTextToPlayer(Player(0),0,0,5,I2S(PSnumber)+", FoundTarget")
      call UnitKill (i)
      set PSnumber = PSnumber - 1
      if PSnumber == 0 then
       //  call DisplayTimedTextToPlayer(Player(0),0,0,5,"timer destroyed")
         call PauseTimer (unitTimer)
         call DestroyTimer (unitTimer)
         set unitTimer = null
      endif   
    endif
    set u = null
endfunction

function PSMove takes nothing returns nothing
local integer i = 1
//call DisplayTimedTextToPlayer(Player(0),0,0,0.1,"timer works")
loop
    exitwhen i > unitMaxIndex
    if unitTaken[i] then
     // call DisplayTimedTextToPlayer(Player(0),0,0,2,"bullet works")
      set PSunitCurrent = i
      set unitX[i] = unitX[i]+Cos(unitDir[i])*35
      set unitY[i] = unitY[i]+Sin(unitDir[i])*35
      call SetUnitX (Unit[i],unitX[i])
      call SetUnitY (Unit[i],unitY[i])
      set unitDis[i] = unitDis[i] - 35
      if unitDis[i] < 36 then
        call RemoveUnit (Unit[i])
      //  call DisplayTimedTextToPlayer(Player(0),0,0,5,I2S(PSnumber)+", unitDis<min")
        call UnitKill (i)
        set PSnumber = PSnumber - 1
        if PSnumber == 0 then
         //  call DisplayTimedTextToPlayer(Player(0),0,0,5,"timer destroyed")
           call PauseTimer (unitTimer)
           call DestroyTimer (unitTimer)
           set unitTimer = null
        endif
      endif
      call PSEnemyGroup (i)
    endif
    set i = i + 1
endloop
endfunction

function PSCreate takes nothing returns nothing
    local unit c = GetTriggerUnit ()
    local location l = GetSpellTargetLoc ()
    call UnitCreate (GetOwningPlayer(c), 'u000', GetUnitX(c), GetUnitY(c), GetUnitFlyHeight(c), Atan2(GetLocationY (l) - GetUnitY (c), GetLocationX (l) - GetUnitX (c)), 1200)
    if PSnumber == 0 then
      set unitTimer = CreateTimer()
      call TimerStart (unitTimer, 0.03, true, function PSMove)
      //call DisplayTimedTextToPlayer(Player(0),0,0,5,"timer starts")
    endif
    set PSnumber = PSnumber + 1
    set c = null
    call RemoveLocation (l)
    set l = null
endfunction

function Trig_PS_Conditions takes nothing returns boolean
    if ( GetSpellAbilityId() == 'A001' ) then
      call PSCreate()
    endif
    return false
endfunction

function InitTrig_PoisonSting takes nothing returns nothing
    local integer index = 0
    local trigger tr = CreateTrigger ()
    loop
      call TriggerRegisterPlayerUnitEvent(tr, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
      set index = index + 1
      exitwhen index == 11
    endloop
    call TriggerAddCondition (tr, Condition (function Trig_PS_Conditions))
    set tr = null
endfunction
endlibrary


Основная проблема не в GroupEnumUnitsInRangeOfLoc или GroupPickRandomUnit.
Если закоментить строчку call PSEnemyGroup (i), т.е. убрать совсем поиск целей, заставляя снаряд всегда лететь вхолостую, то лаги остаються на прежнем уровне.
Прикрепленные файлы
Тип файла: w3x Poison Sting2.w3x (20.1 Кбайт, 11 просмотров )

Отредактировано Fromitt, 19.04.2011 в 22:32.
Старый 14.04.2011, 13:45
J64_

offline
Опыт: 4,724
Активность:
Ты стопитсот раз создаешь и иногда НЕ убираешь(кондишион в группах). Для большей оптим. Юзай глоб группу/точку/фильтр. Точки то вообще то не нужно кроме з пространства, обойдешься двумя реалками. Форгроуп...
Ты в фильтре действия(не надо бжишных гроуп операций, делай свои) делай уже, а не фильтр+форгроуп. Ведь у тя в таком случае буит 2 перебора.
А тк вроде усе норм...
И рекемендую те структуры, удобнее
изучи в/ц джасс
Старый 14.04.2011, 15:39
Fromitt

offline
Опыт: 445
Активность:
Да. Насчет групп верно подмечено. Я понимаю, что это сразу бросается в глаза. Сейчас занят переделкой.
Но.
Не в этом все дело. Можно удалить полностью функции PSEnemyFilter2, PSEnemyFilter, PSEnemyGroup и соответственно вызов call PSEnemyGroup, а утечки остаються в тех же размерах.
Это заставляет искать ошибки в других функциях.
Старый 14.04.2011, 16:07
Elf_Stratigo

offline
Опыт: 4,699
Активность:
попробуй везде поменять местами строчки
set PSnumber = PSnumber - 1
call UnitKill (i)
вообще для движения достаточно одного таймера, но кто уж как напишет...
Старый 14.04.2011, 16:46
Fromitt

offline
Опыт: 445
Активность:
Перестановка строчек ничего не дала, но натолкнула на мысль проверить, останавливается ли таймер. Оказалось, что не всегда. Похоже идея запихнуть удаление таймера в Library UnitLib была изначально провальной.

Отредактировано Fromitt, 14.04.2011 в 17:35.
Старый 14.04.2011, 17:24
JimALIEN
вдупляет sc2 editor
offline
Опыт: 7,176
Активность:
ты после каждого каста запускаеш таймер, который перебирает масив из уже запущеных соплей (которые тоже движуца по своему таймеру, который перебирает весь массив и т.д.) жуть. Либо двигай все по одному таймеру, либо на каждый каст создавай отдельный. Я советую 2е, удобно юзать с хеш таблицами
Старый 15.04.2011, 13:02
Fromitt

offline
Опыт: 445
Активность:
На самом деле таймер один. Да, он перебирает все снаряды, но включается только когда есть запущенные сопли. Проблема была в моей кривой реализации, из-за которой он почемуто не выключался, но я ее исправил.

Кстати вопрос: переменые integer, real, если верить статье Adolf'a, обнулять не нужно?
Старый 15.04.2011, 13:26
Hanabishi
COOL STATUS
offline
Опыт: отключен
Fromitt, нет, не нужно, обнулять нужно только производные handle
читать лучше эту статью
Старый 15.04.2011, 14:06
Ответ

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 04:14.