есть одна 2D карта (по зеленой кнопке)
но код для просчёта коллизий может обработать только 11 юнитов
(если играть всемером - то получится, что можно добавить только 4 доп.юнита на карту)
если сделать 12 или 50 юнитов - то варик просто захлёбывается
(в карте есть счетчик обработки коллизий - максимально 80000 операций в секунду)
есть желающие поковыряться в коде и улучшить его, чтобы он смог обрабатывать 50 юнитов?
коллизии - это столкновение. по X это толкание соседних юнитов вправо влево, по Y это носить на голове или стоять сверху на юните
код карты тут:
EN controlc.com/b12ac4e8
RU controlc.com/dcfc0814
цепочка функций по просчёту коллизий:
main - начало карты
Frame__init - инициализация кадра
Frame__Main - просчет одного кадра (частота 0.02)
Frame__PlayersGroup - просчет группы юнитов
Frame__SquaresMoving - движение юнитов
Frame__MovingY [b==false] - движение по Y
if MushroomMoving_RectCondition "UpWidthOM" + "DownWidthOM"  - сравнение ректов
MushroomMoving_CollisionCheck - проверка на коллизии
set otherx=GetUnitX(OrangeMushroom[j]) + set othery=GetUnitY(OrangeMushroom[j]) - считывание координат
графики:
скриншот карты:
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
3
29
6 месяцев назад
3
Что такое CPS?

есть желающие поковыряться в коде и улучшить его, чтобы он смог обрабатывать 50 юнитов?
Ковыряться в чужом коде после грязного жасса? Извольте.
0
14
6 месяцев назад
Отредактирован host_pi
0
goodlyhero: Попробуйте проверять на коллизию не всех юнитов на карте а только ближайших, например через поиск их в ректе.
а разве именно это не делает эта имеющаяся строка в коде?:
if ContainsCoords(otherx-64,othery-64,otherx+64,othery+64,x,y)==true then
более того - если эту проверку убрать и оставить только считывание координат всех юнитов - то скорость особо не изменится, т.к. тормоза идут именно из-за считывания координат, которые потом сравниваются - близко они или далеко
nazarpunk: Что такое CPS?
счётчик количества отработки функции MushroomMoving_CollisionCheck
варик начинают загружать именно эти две строки:
set otherx=GetUnitX(OrangeMushroom[j])
set othery=GetUnitY(OrangeMushroom[j])
а счётчик считает сколько раз было обращение к этим строкам
1
29
6 месяцев назад
1
а разве именно это не делает эта имеющаяся строка в коде?
Нет, она уже сверяет координаты. Если сверять всех со всеми, то это будет O(n*n). А имелось в виду сверять только ближайшие координаты, чтоб хоть как-то понизить сложность.
варик начинают загружать именно эти две строки:
Зачем получать координаты из игры, если стандартная система перемещений отключена? Почему не хранить их в массиве не пользоваться только Set?
1
8
6 месяцев назад
Отредактирован goodlyhero
1
варик начинают загружать именно эти две строки:
Варкрафт загружает то, что у вас происходит полный перебор всех пар юнитов.
Стандартные варкрафтовские функции в этом плане работают намного умнее и количество юнитов почти не влияет на скорость. Соответственно функция GroupEnumUnitsInRect Вернет вам всех юнитов в квадрате за время. которое не зависит от количества юнитов на карте примерно никак. И это буде примерно бесконечно быстрее на значителньных количествах юнитов.
0
14
6 месяцев назад
Отредактирован host_pi
0
nazarpunk: А имелось в виду сверять только ближайшие координаты, чтоб хоть как-то понизить сложность.
какой нативкой можно сверять ближайшие координаты у других юнитов рядом с заданным?
nazarpunk: Зачем получать координаты из игры, если стандартная система перемещений отключена? Почему не хранить их в массиве не пользоваться только Set?
прекрасное замечание, завтра попробую пошаманить и перевести координаты на глобалки
goodlyhero: EnumUnitsInRect
благодарю, тоже попробую брать чуть расширенный рект юнита и применять к нему EnumUnitsInRect
благо карта позволяет всё измерить сразу же
1
8
6 месяцев назад
Отредактирован goodlyhero
1
какой нативкой можно сверять ближайшие координаты у других юнитов рядом с заданными?
Получить набор ближайших юнитов можно черезк как уже описывалось GroupEnumUnitsInRect. Способа сравнивать по координатам в ванильном варике я не знаю. Не работает, вроде как, на юнитов с локустами, но тут можно придумать много чего.
1
29
6 месяцев назад
1
Стандартные варкрафтовские функции в этом плане работают намного умнее и количество юнитов почти не влияет на скорость.
Они разве не O(n)?
1
12
6 месяцев назад
Отредактирован Daro
1
Видел, что для большей производительности юзали через костыль трек события TriggerRegisterUnitInRange(trig, whichUnit, range, null), это по сути и есть готовая псевдоколлизия между юнитами, но для неё нужно накостыли эвент на выход из зоны и свойство на получения текущего статуса для проверки MushroomMoving_CollisionCheck, можно все коллизии у юнита сохранять в хеш по идишнику и динамический обновлять бд. Но это, как говориться, решение, которое нужно было реализовывать ещё при начале разработки
0
14
6 месяцев назад
Отредактирован host_pi
0
в карте у всех юнитов стоит abiList:
Aloc - москиты locust - что делает юнита некликабельным и не показывает тултип
Avul - неуязвимый invulnerable - что убирает показывание полоски жизни
GroupEnumUnitsInRect и GroupEnumUnitsInRange - не работает с москитами, т.е. юнита с такой абилкой - не добавляет в группу
если убрать Aloc с коробки - то коллизии начинают работать
если убрать Aloc с гриба - то коллизии почему-то не срабатывают когда гриб под коробкой - если коробка сверху, то она проваливается в него, хотя на коробке гриб стоит нормально
после редактирования карты и убирания москитов с коробок такие результаты:
-bridge 12 в новом коде выдает 19200 коллизий против 79200 коллизий в прошлом
варик без пробуксовывания может обрабатывать максимум уже не -bridge 12 а -bridge 18 - 28600 коллизий
-ladder2 10 в новом коде выдает 26300 коллизий против 82000 коллизий в прошлом
варик без пробуксовывания может обрабатывать максимум уже не -ladder2 10 а -ladder2 12 - 32200 коллизий
вот получившийся код через GroupEnumUnitsInRange 200
пока через радиус, с ректом не морочился
код GroupEnumUnitsInRange 200
function UnitIndex takes unit u returns integer
	local integer i=1
	loop
		exitwhen i>PLAYER_MAXINUM+Stage_BoxsCount
		if u==OrangeMushroom[i] then
			set u=null
			return i
		endif
		set i=i+1
	endloop
	set u=null
	return 0
endfunction
function MushroomMoving_CollisionCheck takes integer i,real x,real y returns boolean
	local integer j=1
	local real otherx
	local real othery
	local group G = CreateGroup()
	local unit u=null
	if LevelClearState[i]==false then
		call GroupEnumUnitsInRange(G, x,y, 200, null)
		loop
			set u = FirstOfGroup(G)
			exitwhen u==null
			if MB_Frame_On==1 then
				set MB_CollisionY = MB_CollisionY+1
			endif
			if u!=OrangeMushroom[i] then
				set otherx=GetUnitX(u)
				set othery=GetUnitY(u)
				set j=UnitIndex(u)
				if (GetPlayerSlotState(GetOwningPlayer(OrangeMushroom[j]))==PLAYER_SLOT_STATE_PLAYING or j>PLAYER_MAXINUM) then
					if ContainsCoords(otherx-64,othery-64,otherx+64,othery+64,x,y)==true then
						if PropellyCondition==true then
							if GetUnitTypeId(OrangeMushroom[j])!='orai' then
								set G=null
								set Frame_MainPlayerY=j
								return false
							endif
						else
							set G=null
							set Frame_MainPlayerY=j
							return false
						endif
					endif
				endif
			endif
			call GroupRemoveUnit(G, u)
		endloop
		set G=null
	endif
	return true
endfunction
перехожу к тестам второго способа через глобалки
Загруженные файлы
1
8
6 месяцев назад
1
код GroupEnumUnitsInRange 200
Я просмотрел код.
Из замеченного:
  1. У вас есть вторая функция которая делает также: MushroomMoving_Collision
  2. До возврата через return нужно уничтожать группу через DestroyGroup и потом обнулять группу и юнита.
  3. В целом, вместо ренжа 200 вам хватит и 128
  4. В этот ренж попадает и сам юнит, чего вероятно вам не нужно. Нужно его пропустить, например банальной проверкой:
if(u==<ваш юнит>) then
	call GroupRemoveUnit(G,u)
	set u = FirstOfGroup(G)
endif
2
29
6 месяцев назад
2
До возврата через return нужно уничтожать группу через DestroyGroup и потом обнулять группу и юнита.
Или использовать глобалки и не мастурбировать созданием/удалением.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.