Добрый день, пытаюсь написать код для отлова юнитов получивших урон. Для этого создал два массива:
tUnits, чтобы записывать туда всех юнитов, чтобы потом по юниту искать триггер, привязанный к этому юниту и удалять его.
damagedTriggers, чтобы записывать туда триггеры для всех существующих и появляющихся на игровой карте юнитов.
tUnits, чтобы записывать туда всех юнитов, чтобы потом по юниту искать триггер, привязанный к этому юниту и удалять его.
damagedTriggers, чтобы записывать туда триггеры для всех существующих и появляющихся на игровой карте юнитов.
По плану система должна работать так:
-Вначале в массив добавляются все юниты на карте и для каждого создается триггер;
-Когда, в процессе игры, на карте появляется новый юнит, он тоже добавляется в массив (в коде это не реализовано);
-Когда юнит погибает, он удаляется из массива юнитов, удаляя и привязанный к нему триггер, тем самым освобождается место для новых юнитов;
-Вначале в массив добавляются все юниты на карте и для каждого создается триггер;
-Когда, в процессе игры, на карте появляется новый юнит, он тоже добавляется в массив (в коде это не реализовано);
-Когда юнит погибает, он удаляется из массива юнитов, удаляя и привязанный к нему триггер, тем самым освобождается место для новых юнитов;
Однако столкнулся с проблемой что при смерти юнита триггер и сам юнит из массивов не удаляются, тем самым забивая и без того не сильно большое пространство. Пример ниже на скриншотах.
Старт игры:
После убийства юнита:
У меня есть два варианта почему так происходит:
- У меня ошибки в коде или я использовал не те функции:
- Редактор по каким то причинам не удаляет юнитов и триггеры, а из этого следует что память рано или поздно забьется.
Подскажите пожалуйста, почему так происходит и есть ли возможность это исправить.
Код (только эта библиотека, других функций или триггеров нет):
library UnitDamageTaker initializer Init
globals
private constant integer ALL_UNITS_COUNT = 2048 //Максимальное количество затригеренных юнитов
private region mapArea
private trigger deadTrigger
private trigger array damagedTriggers[ALL_UNITS_COUNT] //На каждого юнита свой триггер
private unit array tUnits[ALL_UNITS_COUNT] //чтобы знать какие юниты затригеренны и какйо конкретный триггер удалять
endglobals
//найти незанятую ячейку массива для записи туда юнита с триггерами
function FindFreeIndex takes nothing returns integer index
local integer i = 0
loop
exitwhen (i==tUnits.size)
if (tUnits[i] == null) then
return i
else
set i = i + 1
endif
endloop
return -1
endfunction
//Найти индекс переданного в функцию юинта в массиве юнитов
function GetUnitIndex takes unit tUnit returns integer index
local integer i = 0
loop
exitwhen (i==tUnits.size)
if (tUnit == tUnits[i]) then
return i
endif
set i = i + 1
endloop
return -1
endfunction
//дебаг функция показывает количество триггеров в массиве, юнитов в массиве, юнитов на карте
function DebugFunction takes nothing returns nothing
local integer i = 0
local integer trgCount = 0
local integer unitCount = 0
local string tMsg = "Триггеров: "
local string uMsg = "Юнитов: "
local string umMsg = "Юнитов на карте: "
loop
exitwhen (i==damagedTriggers.size)
if (damagedTriggers[i]!=null) then
set trgCount = trgCount + 1
endif
if (tUnits[i]!=null) then
set unitCount = unitCount + 1
endif
set i = i + 1
endloop
set tMsg = tMsg + I2S(trgCount)
set uMsg = uMsg + I2S(unitCount)
set umMsg = umMsg + I2S(CountUnitsInGroup(GetUnitsInRectAll(GetPlayableMapRect())))
call BJDebugMsg(tMsg)
call BJDebugMsg(uMsg)
call BJDebugMsg(umMsg)
endfunction
//
//Действия при получении юнитом урона
function DamagedTriggerActions takes nothing returns nothing
local string msg = "юнит " + GetUnitName(GetEventDamageSource()) + " нанес " + R2S(GetEventDamage()) + " урона юниту " + GetUnitName(GetTriggerUnit())
call BJDebugMsg(msg)
endfunction
//Действия при смерти юнита
function DeadTriggerActions takes nothing returns nothing
local integer deadUnitIndex = GetUnitIndex(GetTriggerUnit())
if (deadUnitIndex == -1) then
return
endif
call DestroyTrigger(damagedTriggers[deadUnitIndex])
call RemoveUnit(tUnits[deadUnitIndex])
//дебаг
call DebugFunction()
//
endfunction
//Создание триггера на смерть юнита
function SetDeadUnitTrigger takes nothing returns nothing
set deadTrigger = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( deadTrigger, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddAction(deadTrigger,function DeadTriggerActions)
endfunction
function SetTriggerForUnit takes nothing returns nothing
local unit tUnit = GetEnumUnit()
local integer freeIndex = FindFreeIndex()
//Если свободного места нет, выход из функции
if (freeIndex==-1) then
return
endif
set tUnits[freeIndex] = tUnit
//Создать риггер на получение урона юнитом
set damagedTriggers[freeIndex] = CreateTrigger()
call TriggerRegisterUnitEvent(damagedTriggers[freeIndex], tUnit, EVENT_UNIT_DAMAGED )
call TriggerAddAction(damagedTriggers[freeIndex], function DamagedTriggerActions)
//
endfunction
//Инициализатор библиотеки
function Init takes nothing returns nothing
//На каждого юнита, находящегося на игровой карте, создается триггер получения урона
set mapArea = CreateRegion()
call RegionAddRect(mapArea, GetWorldBounds())
call ForGroupBJ( GetUnitsInRectAll(GetPlayableMapRect()), function SetTriggerForUnit)
//
call SetDeadUnitTrigger()
//дебаг
call DebugFunction()
//
endfunction
endlibrary
Принятый ответ
но опять же что делать со старым триггером.
Попробуй написать set damagedTriggers[deadUnitIndex] = null после DestroyTrigger(damagedTriggers[deadUnitIndex]) ._.
Я уже проверял тему с периодическим уничтожением триггера дабы избавиться от событий несуществующих юнитов, всё работает, события уничтожаются триггер тоже
раскрыть
globals
private region rectRegion
private timer Timer = CreateTimer()
group TempG = CreateGroup()
// trigger gg_trg_ElectricCharge
endglobals
private function ElectricCharge_Actions takes nothing returns boolean
...
return false
endfunction
//========================================================
private function RegistEventA takes nothing returns boolean
call TriggerRegisterUnitEvent(gg_trg_ElectricCharge,GetFilterUnit(),EVENT_UNIT_DAMAGED)
return false
endfunction
private function RegistEvent takes nothing returns nothing
if gg_trg_ElectricCharge != null then
call DestroyTrigger(gg_trg_ElectricCharge)
endif
set gg_trg_ElectricCharge = CreateTrigger( )
call GroupEnumUnitsInRect(TempG,bj_mapInitialPlayableArea,Condition(function RegistEventA))
call TriggerAddCondition(gg_trg_ElectricCharge,Condition(function ElectricCharge_Actions))
call TimerStart(Timer,600.,false,function RegistEvent)
endfunction
private function RegistEventB takes nothing returns boolean
if GetUnitAbilityLevel(GetTriggerUnit(),'Aloc') == 0 then
call TriggerRegisterUnitEvent(gg_trg_ElectricCharge,GetTriggerUnit(),EVENT_UNIT_DAMAGED)
endif
return false
endfunction
function InitTrig_ElectricCharge takes nothing returns nothing
local trigger t = CreateTrigger()
call RegistEvent()
set rectRegion = CreateRegion()
call RegionAddRect(rectRegion,bj_mapInitialPlayableArea)
call TriggerRegisterEnterRegion(t,rectRegion,null)
call TriggerAddCondition(t,Condition(function RegistEventB))
set t = null
endfunction
`
ОЖИДАНИЕ РЕКЛАМЫ...
Чтобы оставить комментарий, пожалуйста, войдите на сайт.
Отредактирован rsfghd