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

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

Закрытая тема
 
Feronetick

offline
Опыт: 86
Активность:
Проблема оптимизации
Уже около месяца изучаю джаз. И вот при создании первого набора скиллов столкнулся с проблемой, которую не могу решить самостоятельно. При неоднократном использовании прыжка игра виснет. Помогите найти сию гигантскую утечку. Так же будет очень интересно выслушать замечания и предложения. Заранее спасибо.
Прикрепленные файлы
Тип файла: w3x LastTestMap.w3x (34.8 Кбайт, 22 просмотров )
Старый 24.02.2011, 21:48
DioD

offline
Опыт: 45,134
Активность:
выкладывай код
Старый 25.02.2011, 06:56
Feronetick

offline
Опыт: 86
Активность:
Код:
globals
    unit array caster
    unit array jump_caster
    unit array jump_bullet
    unit array meteo_1
    unit array meteo_2
    unit array meteo_3
    unit array meteo_4
    real array jump_angle
    real array jump_dist
    real array jump_range
    real array jump_x
    real array jump_y
    trigger array trig_jump
    trigger array trig_rotate
    trigger array trig_destroy
    trigger array trig_meteo_1
    trigger array trig_meteo_2
    trigger array trig_meteo_3
    trigger array trig_meteo_4
    integer array step
    integer array distance
    integer count = 0
endglobals

function jump_reselect takes unit u1, unit u2 returns nothing
    local integer a = 0
    loop
        if IsUnitSelected(u1, Player(a)) then
            call SelectUnitRemoveForPlayer(u1, Player(a))
            call SelectUnitAddForPlayer(u2, Player(a))
        endif
    set a = a + 1
    exitwhen a > 11
    endloop
endfunction

function PolarZ takes real left, real dist returns real
 local real r = dist / 2
 local real Z = 4 * left * r * (1 - left / dist) / dist
return Z
endfunction

function PolarX takes real x, real dist, real ang returns real
    return x + dist * Cos(ang * bj_DEGTORAD)
endfunction

function PolarY takes real y, real dist, real ang returns real
    return y + dist * Sin(ang * bj_DEGTORAD)
endfunction

function DistanceBetweenCoords takes real aX, real aY, real bX, real bY returns real
    local real dx = bX - aX
    local real dy = bY - aY
    return SquareRoot(dx * dx + dy * dy)
endfunction

function AngleBetweenCoords takes real aX, real aY, real bX, real bY returns real
    return bj_RADTODEG * Atan2(bY - aY, bX - aX)
endfunction

function meteoFind takes unit u returns integer
    local integer a = 1
    loop
        exitwhen caster[a] == u or a > 100
        set a = a + 1
    endloop
    if a < 100 then
        return a
    else
        return 0
    endif
endfunction

function jump_allocate takes nothing returns integer
    local integer a = 0
    loop
        set a = a + 1
        exitwhen jump_caster[a] == null
    endloop
    return a
endfunction


Код:
function trig_jump_act takes nothing returns nothing
    local integer a = 0
    local real ang
    local trigger trig = GetTriggeringTrigger()
        loop
            set a = a + 1
        exitwhen trig_jump[a] == trig
        endloop
    if jump_dist[a] <= 10 then
        call BJDebugMsg("jump_dist[" + I2S(a) + "] = " + R2S(jump_dist[a]))
        if meteoFind(jump_bullet[a]) > 0 then
            set caster[meteoFind(jump_bullet[a])] = jump_caster[a]
        endif
        call ShowUnit(jump_caster[a], true)
        call jump_reselect(jump_bullet[a], jump_caster[a])
        call KillUnit(jump_bullet[a])
        call ShowUnit(jump_bullet[a], false)
        call SetUnitX(jump_caster[a], PolarX(jump_x[a], jump_dist[a], jump_angle[a]))
        call SetUnitY(jump_caster[a], PolarY(jump_y[a], jump_dist[a], jump_angle[a]))
        set jump_dist[a] = 0
        call BJDebugMsg(R2S(jump_dist[a]))
        set jump_angle[a] = 0
        call BJDebugMsg(R2S(jump_angle[a]))
        set jump_range[a] = 0
        call BJDebugMsg(R2S(jump_range[a]))
        set jump_x[a] = 0
        call BJDebugMsg(R2S(jump_x[a]))
        set jump_y[a] = 0
        call BJDebugMsg(R2S(jump_y[a]))
        set jump_caster[a] = null
        call TriggerClearActions(trig_jump[a])
        call DisableTrigger(trig_jump[a])
        call TriggerSleepAction(1)
        call DestroyTrigger(trig_jump[a])
        call RemoveUnit(jump_bullet[a])
        set jump_bullet[a] = null
        call BJDebugMsg(GetUnitName(jump_bullet[a]))
        set trig = null
        set trig_jump[a] = null
    endif
    if jump_dist[a] > 10 then
        set jump_dist[a] = jump_dist[a] - 10
        call SetUnitX(jump_bullet[a], PolarX(jump_x[a], jump_dist[a], jump_angle[a]))
        call SetUnitY(jump_bullet[a], PolarY(jump_y[a], jump_dist[a], jump_angle[a]))
        call SetUnitFlyHeight(jump_bullet[a], PolarZ(jump_dist[a], jump_range[a]), 0)
        set trig = null
    endif
endfunction


Код:
function Trig_skill_Actions takes nothing returns nothing
    local unit u = GetSpellAbilityUnit()
    local integer loopint
    local integer num
    local real xU = GetUnitX(u)
    local real yU = GetUnitY(u)
    if GetSpellAbilityId() == 'JUMP' then
        set num = jump_allocate()
        set jump_caster[num] = u
        set jump_x[num] = GetSpellTargetX()
        set jump_y[num] = GetSpellTargetY()
        set jump_angle[num] = AngleBetweenCoords(jump_x[num], jump_y[num], xU, yU)
        set jump_dist[num] = DistanceBetweenCoords(xU, yU, jump_x[num], jump_y[num])
        set jump_range[num] = jump_dist[num]
        set jump_bullet[num] = CreateUnit(GetOwningPlayer(u), 'XCOS', xU, yU, AngleBetweenCoords(xU, yU, jump_x[num], jump_y[num]))
        call UnitAddAbility(jump_bullet[num], 'Amrf')
        call UnitRemoveAbility(jump_bullet[num], 'Amrf')
        if meteoFind(jump_caster[num]) > 0 then            
            set caster[meteoFind(jump_caster[num])] = jump_bullet[num]
        endif
        call jump_reselect(jump_caster[num], jump_bullet[num])
        call ShowUnit(jump_caster[num], false)
        set trig_jump[num] = CreateTrigger()
        call TriggerRegisterTimerEvent(trig_jump[num], 0.01, true)
        call TriggerAddAction(trig_jump[num], function trig_jump_act)
    endif
    set u = null
endfunction

//===========================================================================
function InitTrig_skill takes nothing returns nothing
    set gg_trg_skill = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_skill, EVENT_PLAYER_UNIT_SPELL_CAST)
    call TriggerAddAction(gg_trg_skill, function Trig_skill_Actions)
endfunction
Старый 25.02.2011, 08:58
ScorpioT1000
Работаем
offline
Опыт: отключен
TriggerRegisterTimerEvent(trig_jump[num], 0.01, true)
заменить на 0.04
Старый 25.02.2011, 10:33
Feronetick

offline
Опыт: 86
Активность:
Похоже, что помогло. Спасибо. Что за странное явление?

Feronetick добавил:
Я полагаю, что вызов trig_jump_act проходил медленнее одной сотой секунды?
Старый 25.02.2011, 10:53
ScorpioT1000
Работаем
offline
Опыт: отключен
число действий триггеров за период в 0.01 сек превысило число инструкций самого движка игры =) ну т.е. при низкой производительности там начинает забиваться стек, хотя точно не знаю, вобзе это всё от компа зависит. Но лучше не юзать меньше 0.04
Старый 25.02.2011, 12:30
Master_chan
Полуночный командир
offline
Опыт: 15,660
Активность:
ScorpioT1000:
начинает забиваться стек
от компа это не очень то и зависит... Если таймеров с 0.01 слишком много лагает на всех компах, что семилетней давности, что новых Hi-End машинах.
Старый 25.02.2011, 15:06
DioD

offline
Опыт: 45,134
Активность:
3125 период на 32 фрейма в секунду.
Старый 25.02.2011, 15:08
Method

offline
Опыт: 152
Активность:
Master_chan, у меня не супер компьютер с шестью и более процессорами но код написанный ниже обробатывает без проблем с повтором каждые 0.01
function UMove takes nothing returns nothing
    local group g = CreateGroup()
    local unit u = GetEnumUnit()
    local integer i = GetUnitUserData(u)
    local real f = (GetUnitFacing(u)*0.01745328)
    local real x = GetUnitX(u)+SSIndex[i]*Cos(f)
    local real y = GetUnitY(u)+SSIndex[i]*Sin(f)
    local integer d = GetPlayerId(GetOwningPlayer(u))
    local unit e
    call SetUnitPosition(u,x,y)
    call GroupEnumUnitsInRange(g,x,y,50,null)
    set e = FirstOfGroup(g)
    loop
        if GetWidgetLife(e) > 0 then
            if IsUnitInGroup(e,STargets[i]) == false then
                if IsUnitEnemy(e,GetOwningPlayer(u)) then
                    call GroupAddUnit(STargets[i],e)
                    call UnitDamageTarget(u,e,(DSimple[i]*D2I(d)),true,false,ATTACK_TYPE_HERO,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_​WHOKNOWS)
                elseif (e == archa[d]) then
                    if (SimpleDist[i] > 220) then
                        call GroupAddUnit(STargets[i],e)
                        call UnitDamageTarget(u,e,(DSimple[i]*D2I(d)),true,false,ATTACK_TYPE_HERO,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_​WHOKNOWS)
                    endif
                endif
            endif
        endif
        call GroupRemoveUnit(g,e)
        set e = FirstOfGroup(g)
        exitwhen (e == null)
    endloop
    set SimpleDist[i] = SimpleDist[i] + SSIndex[i]
    if (SimpleDist[i] > SRange[SimpleLB[i]]) then
        set CountS = CountS - 1
        if (CountS < 1) then
            call DisableTrigger(GetTriggeringTrigger())
        endif
        call DestroyGroup(STargets[i])
        set STargets[i] = null
        call RemoveUnit(u)
    endif
    call DestroyGroup(g)
    set g = null
    set u = null
    set e = null
endfunction
Вызов начинается с этой функции:
function UMoveStart takes nothing returns nothing
    call ForGroup(udg_SGroup,function UMove)
endfunction
Я бы использовал его каждые 0.04 секунды, но скорость перемещаемого объекта замедляется. При увеличении дистанции перемещения пик юнитов не такой как хотелось бы.
Старый 25.02.2011, 16:54
Master_chan
Полуночный командир
offline
Опыт: 15,660
Активность:
Method, ты не прошарил что я написал. Вся тема сводится к мысли "Не используй 0.01"
Старый 25.02.2011, 16:55
Feronetick

offline
Опыт: 86
Активность:
Хмм-м-м. В таком случае будет довольно сложно сделать более-менее плавное движение юнита. Хотя, возможно стоит попробовать просто отдавать приказ двигаться и менять высоту постепенно?
Старый 25.02.2011, 18:58
Clamp
Lost in space
offline
Опыт: 71,158
Активность:
Feronetick, 0,04 = 25 кадров/секунду
вполне достаточно
Старый 25.02.2011, 19:10
DioD

offline
Опыт: 45,134
Активность:
3125 ближайшее к 30 целое число кадров в секунду, вашу маму вы что такие тупые то, написано ведь.
Старый 25.02.2011, 20:02
ScorpioT1000
Работаем
offline
Опыт: отключен
По стандарту ru.wikipedia.org/wiki/NTSC надо юзать 0.0333333 =) оно стремится к 30 кадрам в секунду
Старый 25.02.2011, 20:35
DioD

offline
Опыт: 45,134
Активность:
03125 не будет вызывать лишний кадр каждую 33ю секунду
Старый 25.02.2011, 20:41
Feronetick

offline
Опыт: 86
Активность:
Эм... Я ставил 0.04 и нужная мне скорость прыжка выглядит довольно-таки урывчато.
Feronetick добавил:
На 0.02 всё похоже на "нормально". Хотя, мне теперь кажется, что стоит всё-таки доводить до "очень хорошо". И всё-таки, стоит ли пробовать слать юнита двигаться к точке?
Старый 25.02.2011, 22:41
alexprey
познающий Unity
offline
Опыт: 68,501
Активность:
Feronetick, еще на будущее если в переодических таймерах юзать BJDebuMsg, то приведет к высоким лагам (хз почему). Проверено
Старый 25.02.2011, 23:53
Feronetick

offline
Опыт: 86
Активность:
Окей. Спасибо, учту.
Старый 26.02.2011, 00:02
Закрытая тема

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

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

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

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



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