www.wc3maps.clan.su


Понедельник, 23.12.2024, 09:21


Приветствую Вас Гость | RSS


Главная | Статьи по Warcraft 3 Картостроения истирия Дота warcraft 3 | Регистрация | Вход
Меню сайта

категории
Статьи о картостроении [75]
Статьи о картостроении

Нашь опрос
Вы картостроитель?
Всего ответов: 2273

Статистика
Яндекс.Метрика
Онлайн всего: 1
Гостей: 1
Пользователей: 0

Форма входа


Майки

Главная » Статьи » Картостроение » Статьи о картостроении

Jass: проблемы Кеша и РБ!!!
Читатель, на первых порах тебе важнее понять принцип работы SCV и научиться его применять. Но в реальности применение системы return bug + Кеш порождает определенные проблемы, которые я постараюсь рассмотреть в этом приложении.

1. Глюки нескольких запусков.
При запуске сценария мы создаем в памяти Кеш и делаем в него записи. Когда мы выходим из сценария, записи должны удаляться. Должны то должны, но иногда этого не происходит. И тогда при следующем запуске игры могут остаться записи, относящиеся к несуществующим объектам. Это чревато ужасными глюками. Я сам с этим столкнулся и долго не мог понять, почему глючит код, в котором не может быть никаких ошибок. И только проверив все самым тщательным образом, обнаружил, что записи не стерты.

К этому багу мне удалось найти противоядие. Вместо стандартной инициализации Кеша, я делаю следующее:

Create a game cache from SCV.w3v
Clear (Last created game cache)
Create a game cache from SCV.w3v
Set cache = (Last created game cache)

Т.е. очищаю Кеш и инициализирую заново. После этого можно быть уверенным, что Кеш будет очищен.

2. Скорость скриптов.
Существует доказательство того, что 1 обращение к Кешу (чтение/запись) раз в 10 медленнее, чем обращение к переменным.

Для некоторых любителей оптимизации это стало поводом отказаться от Кеша и разрабатывать альтернативные системы при помощи масствов. В то же время, я не советую следовать их примеру. Да, я не исключаю, что кому-то из jass-еров удастся разработать более быстрые системы, но вряд ли получится сделать их более простыми, универсальными и доступными, чем SCV.

Практика показывает, что даже для такой карты как Дота применение Кеша вполне приемлемо. Если качество SCV вас устраивает, то нет смысла тратить массу времени и сил на разработку собственных систем.

Кстати говоря, скорость большинства внутренних функций war3 еще меньше, чем обращение к Кешу. Поэтому, если ваш скрипт работает медленно – 99% что проблема в алгоритме, а не Кеше.

Впрочем, кое-какие выводы для себя можно для себя сделать.
1. Кеш лучше всего использовать в случаях, когда в этом есть реальная необходимость. Например, когда по ходу игры нужно одному объекту сопоставить другой объект. Если же у вас имеются данные, которые хранятся в течение всей игры, их лучше хранить в массивах.
2. Старайтесь минимизировать число параметров, которые требуется передавать через Кеш в триггерах с малыми периодами.
3. Если внутри одной и той же функции нужно несколько раз обратиться к одной и той же записи – поместите эту запись в переменную и обращайтесь к переменной.

3. Баг РБ.
Не очень давно был обнаружен баг внутри РБ (баг в баге). Суть в следующем: в результате определенных действий, игровой объект (чаще всего, юнит) может исчезнуть из игры. А записи в Кеше останутся. Например, если уже был запущен какой-то триггер, делающий отсроченный действия с этим объектом. Но еще до того, как отсроченное действие будет выполнено, в игре могут появиться новые объекты. И существует шанс, что игра запишет один из них именно в ту ячейку памяти, в которой раньше был записан старый объект.
Что получится? Игра должна была совершить определенное действие со старыми объектом, а произведет с новым. Потому что указатель на старый и новый юнит совпадают.

Подобная проблема вполне может возникнуть в АОСах. Допустим у вас есть триггерное заклинание, которое при помощи таймер, РБ и Кеша периодически наносит повреждения юниту-цели. Но вот, юнита-цель убивает какой-нибудь артиллерист. Юнит не просто умирает, а взрывается. Т.е. сразу после смерти он исчезает из игры. Но в АОСах постоянно создаются все новы юниты. И вот, создается новый юнит в той же ячейке, что и старый. И тогда мы получим, что периодические повреждения будут наноситься какому-то случайному юниту. Т.е. получили баг.

Как с этим багом бороться? Вообще-то если вы будете все аккуратно программировать, то баг просто не возникнет. Всегда можно отловить смерть юнита (в момент смерти юнит еще присутствует в игре). Можно сопоставить юниту все запущенные для него таймеры. При смерти юнита предусмотреть, чтобы с этими таймерами не возникало проблем. Затем, удаляем все записи Кеша, связанные с умершим юнитом.

Есть еще один прием. Дело в том, что новый юнит может занять место старого только при условии, что на старый юнит нет ссылок из переменных (неважно, глобальных или локальных). Можно использовать такой прием. Триггер, который сработает при смерти юнита:

local unit u = GetDyingUnit()
call PolledWait(60.0)
call flush_object(u)
set u = null

Т.е. любой умерший юнит попадает в локальную переменную на 60 секунд. После чего записи из Кеша отчищаются. Для большинства отстроченных действий 60 секунд вполне хватит, чтобы обнаружить, что юнит-цель уже мертв.

Кстати, можем получить и другую сторону этого бага. Даже если ничего не будет записано в пустую ячейку удаленного юнита, отсроченные действия могут не предусмотреть наличие юнита-пустышки там, где раньше был живой юнит.

Реальный пример. Я долго не мог понять, почему глючит моя триггерная аура. Технология ауры заключалась в том, что создавался периодический триггер. Ему сопоставлялась группа юнитов, на которых действует аура. В триггере нужно периодически перебирать юнитов из группы. За это отвечал такой блок:

set k2 = CountUnitsInGroup(gr)
set k = 1
loop
exitwhen k>k2
set u = FirstOfGroup(gr)
...
call GroupRemoveUnit(gr,u)
set k = k + 1
endloop

Но если в группу gr зачешется уже убранный из игры юнит – скрипт прекратит выполняться, когда дойдет до строчки set u = FirstOfGroup(gr). Точнее, он вылетит, когда, первым в группе окажется пустой юнит. При этом вы никак не сможете избавиться от этого глючного юнита. Его уже невозможно удалить из группы. Пришлось немного помучаться, пока я не нашел противоядие к этому багу:

set gr2 = CreateGroup()
call GroupAddGroup( gr, gr2 )
set k2 = CountUnitsInGroup(gr2)
set k = 1
loop
exitwhen k>k2
set u = FirstOfGroup(gr2)
...
call GroupRemoveUnit(gr2,u)
set k = k + 1
endloop

Т.е. мы делаем еще одну группу. В эту группу помещаем все юниты из первой группы (не надо бояться – глючный юнит невозможно добавить в новую группу, также как невозможно удалить его из старой группы). Далее перебираем не первую, а вторую группу.

Категория: Статьи о картостроении | Добавил: Admin (26.12.2009)
Просмотров: 385 | Теги: Jass: проблемы Кеша и РБ!!! | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Поиск

Друзья сайта
Вот



Антибаннер
Описание:
Adguard удаляет рекламный спам, ускоряет загрузку страниц и экономит трафик.

Последние файлы

29.03.2020

Скачать (3.87 Mb)

01.09.2017

Скачать ()

01.09.2017

Скачать ()

02.07.2017

Скачать (8 МБ)

03.12.2014

Скачать (546 MB)

22.11.2014

Скачать ()

19.09.2014

Скачать (137 mb)

17.09.2014

Скачать (100 mb)

17.09.2014

Скачать (133 mb)

31.07.2013

Скачать (7мб)



Wc3maps © 2024