Перейти к содержимому

Планировщик

Планировщик отвечает сразу на два вопроса:

  • когда запустить код? — на каждом кадре, раз в десять тиков, после паузы;
  • как его остановить? — явно через Cancel() или вместе со scope компонента.

Импортируйте планировщик из той среды, где должна выполняться работа. Клиент наблюдает за отрисованными кадрами, Reflex — за тиками серверной симуляции.

import { scheduler } from "@killscript/sdk/client";
// Каждый клиентский кадр.
const frame = scheduler.frame(updateCamera);
// Примерно два раза в секунду.
const interval = scheduler.every(0.5, updateHud);
// Один раз через 10 игровых тиков.
const delayed = scheduler.afterTicks(10, showReadyState);
frame.Cancel();
interval.Cancel();
delayed.Cancel();

В Reflex импортируйте @killscript/sdk/server и используйте scheduler.tick() вместо frame().

МетодДля чего подходитКак останавливается
frame(callback)Камера, HUD и чтение клиентского вводаCancel()
tick(callback)Проверки серверной симуляцииCancel()
after(seconds, callback)Простая однократная задержка игрыНе отменяется
afterTicks(ticks, callback)Отменяемый дедлайн в тикахСам или через Cancel()
every(seconds, callback)Лёгкая периодическая задачаCancel()
everyTicks(ticks, callback)Периодическая серверная задачаCancel()
until(predicate, callback)Ожидание появления нужного состоянияСам или через Cancel()
debounce(key, seconds, callback)Запуск после прекращения серии вызововЗаменяется следующим вызовом с тем же ключом
throttle(key, seconds, callback)Не больше одного запуска за интервалВозвращает, был ли запуск

every() не пытается воспроизвести пропущенные вызовы после медленного кадра. Следующий запуск отсчитывается с момента текущего. Для обновления интерфейса и периодического поиска объектов это обычно правильное поведение.

Например, локального игрока может ещё не существовать в момент загрузки модуля. until() позволяет дождаться его без вечной ручной проверки:

const waitForPlayer = scheduler.until(
() => Agents.GetLocalAgent() !== undefined,
() => initializeForPlayer(Agents.GetLocalAgent()!),
);

Подписку всё ещё можно отменить, если компонент выключится до появления игрока.

Debounce подходит для тяжёлого обновления, которое должно произойти один раз после серии изменений:

function settingsChanged(): void {
scheduler.debounce("settings:rebuild-hud", 0.2, rebuildHud);
}

debounce() не возвращает подписку. Новый вызов с тем же ключом отменяет ожидающий обработчик, но scope компонента не может отменить его напрямую. Обработчик должен безопасно завершаться, если компонент уже выключен.

Throttle выполняет первый вызов сразу, а остальные отклоняет до конца интервала:

function reportPosition(): void {
scheduler.throttle("debug:position", 1, () => {
print(`${Agents.GetLocalAgent()?.Movement.Position}`);
});
}

Ключи общие для всего собранного клиентского или серверного скрипта. Добавляйте к обычным ключам имя компонента, чтобы разные файлы случайно не подавляли друг друга.