Представьте себе задачу: у вас есть игра, и вам нужно, чтобы она работала с частотой 60 fps на 60-герцовом мониторе. Ваш компьютер достаточно быстр для того, чтобы рендеринг и обновление занимали несущественное количество времени, поэтому вы включаете vsync и пишете такой игровой цикл:
while(running)
Очень просто! Теперь игра работает с 60fps и всё идёт как по маслу. Готово. Спасибо, что прочитали этот пост.
Ну ладно, очевидно, что всё не так хорошо. Что если у кого-то слабый компьютер, который не может рендерить игру с достаточной для обеспечения 60fps скоростью? Что если кто-то купил один из тех крутых новых 144-герцовых мониторов? Что если он отключил в настройках драйвера vsync?
Вы можете подумать: мне нужно где-то измерять время и обеспечить обновление с правильной частотой. Это сделать довольно просто — достаточно накапливать время в каждом цикле и выполнять обновление каждый раз, когда он превосходит порог в 1/60 секунды.
ИГРАЕМ В АЙЗЕКА И JACKBOX PARTY PACK 3, 4, 5, 6, 7, 8
while(running) < deltaTime = CurrentTime()-OldTime; oldTime = CurrentTime(); accumulator += deltaTime; while(accumulator >1.0/60.0) < update(); accumulator -= 1.0/60.0; >render(); display(); >
Готово, проще некуда. На самом деле есть куча игр, в которых код по сути выглядит именно так. Но это неправильно. Это подходит для регулировки таймингов, но приводит к проблемам с дёрганьем (stuttering) и прочим рассогласованиям.
Очень часто встречается такая проблема: кадры отображаются не ровно 1/60 секунды; даже когда vsync включен, всегда присутствуют небольшой шум во времени их отображения (и в точности таймера ОС). Поэтому будут возникать ситуации, когда вы рендерите кадр, а игра считает, что время повторного обновления ещё не настало (потому что аккумулятор на крошечную долю запаздывает), поэтому она просто снова повторяет тот же кадр, но теперь игра запаздывает на кадр, поэтому выполняет двойное обновление. Вот и дёрганье!
Погуглив, можно найти несколько готовых решений для устранения этого дёрганья. Например, игра может использовать переменный, а не постоянный шаг времени, и просто полностью отказаться от аккумуляторов в коде таймингов. Или можно реализовать постоянный шаг времени с интерполирующим рендерером, описанный в довольно известной статье «Fix Your Timestep» Гленна Филдера. Или можно переделать код таймера так, чтобы он был немного более гибким, как описано в посте «Frame Timing Issues» Slick Entertainment (к сожалению, этого блога уже нет).
Нечёткие тайминги
Метод Slick Entertainment с «нечёткими таймингами» в моём движке было реализовать проще всего, потому что он не требовал изменений в логике игры и рендеринге. Поэтому в The End is Nigh я использовал его. Достаточно было просто вставить его в движок. По сути, он просто позволяет игре обновляться «немного раньше», чтобы избежать проблем с рассогласованием таймингов. Если в игре включен vsync, то он просто позволяет использовать в качестве основного таймера игры vsync, и обеспечивает плавную картинку.
Q & A : How to unlock 60fps Heartstone ? #hearthstone #60fps
Вот как код обновления выглядит сейчас (игра «может работать» при 62 fps, но всё равно обрабатывает каждый шаг времени так, как будто работает при 60fps. Не совсем понимаю, зачем ограничивать его так, чтобы значения аккумулятора не опускались ниже 0, но без этого код не работает). Можно интерпретировать это так: «игра обновляется с фиксированным шагом, если рендерится в интервале от 60fps до 62fps»:
while(accumulator > 1.0/62.0)< update(); accumulator -= 1.0/60.0; if(accumulator
Если включён vsync, то он по сути позволяет игре работать с фиксированным шагом, который совпадает с частотой обновления монитора, и обеспечивает плавную картинку. Основная проблема здесь в том, что при отключенном vsync игра будет работать немного быстрее, но разница столь незначительна, что никто её не заметит.
Спидраннеры. Спидраннеры заметят. Вскоре после выхода игры они заметили, что некоторые люди в списках рекордов спидрана имели более плохое время прохождения, но по подсчёту оказавшееся более хорошим, чем у других. И непосредственной причиной этого была нечёткость таймингов и отключение vsync в игре (или 144-герцовые мониторы). Поэтому стало очевидно, что нужно выключать эту нечёткость при отключении vsync.
Ой, но ведь мы никак не может проверить, отключен ли vsync. В ОС для этого нет вызоWow, и хотя мы можем запрашивать из приложения включение или отключение vsync, на самом деле это полностью зависит от ОС и графического драйвера.
Единственное, что можно сделать — отрендерить кучу кадров, попробовать измерить время выполнения этой задачи, а затем сравнить, занимают ли они примерно одинаковое время. Именно так я и сделал для The End is Nigh. Если в игре не включен vsync с частотой 60 Гц, то она откатывается к исходному таймеру кадров со «строгими 60 fps». Кроме того, я добавил в файл конфигурации параметр, принуждающий игру не использовать нечёткость (с основном для спидраннеров, которым нужно точное время) и добавил для них точный обработчик внутриигрового таймера, позволяющий использовать autosplitter (это скрипт, работающий с таймером атомного времени).
Некоторые пользователи по-прежнему жаловались на возникающие иногда дёрганья отдельных кадров, но они казались настолько редкими, что их можно было объяснить событиями ОС или другими внешними причинами. Ничего особо страшного. Верно?
Просматривая недавно свой код таймера, я заметил нечто странное. Аккумулятор смещался, каждый кадр занимал чуть больше времени, чем 1/60 секунды, поэтому периодически игра думала, что запаздывает на кадр, и выполняла двойное обновление. Оказалось, что мой монитор работает с частотой 59,94 Гц, а не 60 Гц. Это означало, что каждые 1000 кадров ему приходится выполнять двойное обновление, чтобы «догнать». Однако это очень просто исправить — достаточно изменить интервал допустимых частот кадров (не с 60 до 62, а с 59 до 61).
while(accumulator > 1.0/61.0)< update(); accumulator -= 1.0/59.0; if(accumulator
Описанная выше проблема с отключенным vsync и мониторами высокой частоты по-прежнему сохраняется, и к нему применимо то же решение (откат к строгому таймеру, если монитор не синхронизирован vsync на 60).
Но как узнать, подходящее ли это решение? Как убедиться, что оно будет правильно работать на всех сочетаниях компьютеров с разными типами мониторов, с отключенным и включенным vsync, и так далее? Очень сложно отслеживать все эти таймерные проблемы в голове, и разбираться что вызывает рассинхронизацию, странные циклы и тому подобное.
Симулятор монитора
Пытаясь придумать надёжное решение «проблемы 59,94-герцового монитора», я осознал, что не могу просто выполнять проверки методом проб и ошибок, надеясь найти надёжное решение. Мне нужен был удобный способ тестирования разных попыток написания качественного таймера и простой способ проверки, вызывает ли он дёрганье или сдвиг времени в разных конфигурациях мониторов.
На сцене появляется Monitor Simulator. Это написанный мной «грязный и быстрый» код, симулирующий «работу монитора», и по сути выводящий мне кучу чисел, дающих представление о стабильности каждого тестируемого таймера.
Например, для простейшего таймера из начала статьи выводятся такие значения:
20211012021011202111020211102012012102012[. ]
TOTAL UPDATES: 10001
TOTAL VSYNCS: 10002
TOTAL DOUBLE UPDATES: 2535
TOTAL SKIPPED RENDERS: 0
GAME TIME: 166.683
SYSTEM TIME: 166.7
Сначала код выводит для каждого эмулируемого vsync число количества «обновлений» игрового цикла после предыдущего vsync. Любые значения, отличающиеся от сплошных 1, приводят к дёрганой картинке. В конце код выводит накопившуюся статистику.
При использовании «нечёткого таймера» (с интервалом 60–62fps) на 59,94-герцовом мониторе код выводит следующее:
111111111111111111111111111111111111111111111[. ]
TOTAL UPDATES: 10000
TOTAL VSYNCS: 9991
TOTAL DOUBLE UPDATES: 10
TOTAL SKIPPED RENDERS: 0
GAME TIME: 166.667
SYSTEM TIME: 166.683
Дёрганье кадра возникает очень редко, поэтому его может быть сложно заметить при таком количестве 1. Но выводимая статистика чётко показывает, что игра выполнила здесь несколько двойных обновлений, что приводит к дёрганью. В исправленной версии (с интервалом 59–61 fps) присутствует 0 пропущенных или двойных обновлений.
Также можно отключить vsync. Остальные данные статистики становятся неважными, но это чётко показывает мне величину «сдвига времени» (сдвига системного времени относительно того, где должно находиться игровое время).
GAME TIME: 166.667
SYSTEM TIME: 169.102
Именно поэтому при отключенном vsync нужно переключаться на строгий таймер, иначе эти расхождения со временем накапливаются.
Если я присвою времени рендеринга значение .02 (то есть для рендеринга нужно «больше, чем кадр»), то снова получу дёрганье. В идеале паттерн игры должен выглядеть как 202020202020, но он немного неравномерен.
В этой ситуации этот таймер ведёт себя немного лучше предыдущего, но становится всё запутаннее и всё сложнее разобраться, как и почему он работает. Но я ведь просто могу засунуть тесты в этот симулятор и проверить, как они себя ведут, а разбираться в причинах можно и позже. Пробы и ошибки, детка!
while(accumulator >= 1.0/61.0)< simulate_update(); accumulator -= 1.0/60.0; if(accumulator < 1.0/59.0–1.0/60.0) accumulator = 0; >
Можете скачать симулятор монитора и самостоятельно проверить разные методы подсчёта таймингов. Напишите мне, если найдёте что-нибудь получше.
Я доволен своим решением не на 100% (в нём всё равно требуется хак с «распознаванием vsync» и могут возникать единичные дёрганья при рассинхронизации), но я считаю, что он почти так же хорош, как и попытка реализации игрового цикла с фиксированным шагом. Частично эта проблема возникает потому, что очень сложно определить параметры того, что считается здесь «приемлемым».
Главная сложность заключается в компромиссе между сдвигом времени и двойными/пропущенными кадрами. Если запустить 60-герцовую игру на 50-герцовом PAL-мониторе… то каким будет верное решение? Хотите ли вы дикого дёрганья, или заметно более медленной работы игры? Оба варианта кажутся плохими.
Отделённый рендеринг
В предыдущих методах я описывал то, что называю «рендерингом с фиксированным шагом» (lockstep rendering). Игра обновляет своё состояние, затем выполняет рендеринг, а при рендеринге она всегда отображает наиболее свежее состояние игры. Рендеринг и обновление соединены вместе.
Но можно их разделить. Именно это делает метод, описанный в посте «Fix Your Timestep». Я не буду повторяться, вам определённо стоит прочитать этот пост. Это (насколько я понимаю) «отраслевой стандарт», используемый в AAA-играх и таких движках, как Unity и Unreal (однако в напряжённых активных 2D-играх обычно предпочитают использовать фиксированный шаг (lockstep), потому что иногда просто необходима точность, которую даёт этот метод).
Но если описать вкратце пост Гленна, то в нём просто описывается метод обновления с фиксированной частотой кадров, но при рендеринге выполняется интерполяция между «текущим» и «предыдущим» состоянием игры, а текущее значение аккумулятора используется как величина интерполяции. При таком способе можно выполнять рендеринг с любой частотой кадров и обновлять игру с любой частотой, а картинка всегда будет плавной. Никакого дёрганья, работает универсально.
while(running)< computeDeltaTimeSomehow(); accumulator += deltaTime; while(accumulator >= 1.0/60.0) < previous_state = current_state; current_state = update(); accumulator -= 1.0/60.0; >render_interpolated_somehow(previous_state, current_state, accumulator/(1.0/60.0)); display(); >
Вот так, элементарно. Проблема решена.
Теперь нужно просто сделать так, чтобы игра могла рендерить интерполированные состояния… но постойте, на самом деле это совсем непросто. В посте Гленна просто допускается, что это можно сделать. Достаточно легко кэшировать предыдущее положение игрового объекта и интерполировать его перемещения, но в состояние игры входит гораздо больше всего. Нужно учитывать в нём состояния анимации, создание и уничтожение объектов, и ещё кучу всякого.
Плюс в логике игры нужно учитывать, телепортируется ли объект или его нужно плавно двигать, чтобы интерполятор не делал ложных предположений о пути, проделанным игровым объектом в его текущее положение. Настоящий хаос может возникнуть с поворотами, особенно если за один кадр поворот объекта может смениться больше, чем на 180 градусов. А как правильно обрабатывать создаваемые и уничтожаемые объекты?
В данный момент я как раз работаю над этой задачей в своём движке. По сути, я просто интерполирую перемещения, а всё прочее оставляю, как есть. Вы не заметите дёрганья, если объект не движется плавно, поэтому пропуск кадров анимации и рассинхронизация создания/уничтожения объекта вплоть до одного кадра не станут проблемой, если всё остальное выполняется плавно.
Однако странно то, что по сути этот метод рендерит игру в состоянии, запаздывающем на 1 состояние игры от того, где сейчас находится симуляция. Это незаметно, но может соединяться с другими источниками задержек, например, задержкой ввода и частотой обновления монитора, поэтому те, кому нужен максимально отзывчивый игровой процесс (я говорю про вас, спидраннеры), скорее всего предпочтут, чтобы в игре использовался lockstep.
В своём движке я просто даю возможность выбора. Если у вас 60-герцовый монитор и быстрый компьютер, то лучше всего использовать lockstep со включенным vsync. Если у монитора нестандартная частота обновления, или ваш слабый компьютер не может постоянно рендерить 60 кадров в секунду, то включайте интерполяцию кадров. Я хочу назвать эту опцию «unlock framerate» («разблокировать частоту кадров»), но люди могут подумать, что это просто означает «включите эту опцию, если у вас хороший компьютер». Однако эту проблему можно решить позже.
Вообще-то есть метод, позволяющий обойти эту проблему.
Обновления с переменным шагом времени
Меня многие спрашивали, почему бы просто не обновлять игру с переменным шагом времени, а программисты-теоретики часто говорят: «если игра написана ПРАВИЛЬНО, то можно просто обновлять её с произвольным шагом времени».
while(running)
Никаких странностей с таймингами. Никакого странного интерполяционного рендеринга. Всё просто, всё работает.
Вот так, элементарно. Проблема решена. И теперь навсегда! Лучшего результата добиться невозможно!
Теперь достаточно просто сделать так, чтобы игровая логика работала с произвольным шагом времени. Это ведь просто, достаточно заменить весь такой код:
position += speed;
position += speed * deltaTime;
и заменить вот такой код:
speed += acceleration; position += speed;
speed += acceleration * deltaTime; position += speed * deltaTime;
и заменить вот такой код:
speed += acceleration; speed *= friction; position += speed;
Vec3D p0 = position; Vec3D v0 = velocity; Vec3D a = acceleration*(1.0/60.0); double f = friction; double n = dt*60; double fN = pow(friction, n); position = p0 + ((f*(a*(f*fN-f*(n+1)+n)+(f-1)*v0*(fN-1)))/((f-1)*(f-1)))*(1.0/60.0); velocity = v0*fN+a*(f*(fN-1)/(f-1));
Откуда это всё взялось?
Последняя часть в буквальном смысле скопирована из вспомогательного кода моего движка, выполняющего «действительно корректное, не зависящее от частоты кадров движение с ограничивающим скорость трением». В нём есть немного мусора (эти умножения и деления на 60). Но это «правильная» версия кода с переменным шагом времени для предыдущего фрагмента. Я вычислял её больше часа при помощи Wolfram Alpha.
Теперь меня могут спросить, почему бы не сделать вот так:
speed += acceleration * deltaTime; speed *= pow(friction, deltaTime); position += speed * deltaTime;
И хотя это как будто сработает, на самом деле так делать неправильно. Можете проверить сами. Выполните два обновления со значением deltaTime = 1, а затем выполните одно обновление с deltaTime = 2, и результаты будут отличаться.
Обычно мы стремимся, чтобы игра работала согласованно, поэтому такие расхождения не приветствуются. Вероятно, это достаточно хорошее решение, если точно знать, что deltaTime всегда примерно равно одному значению, но тогда нужно написать код, обеспечивающий выполнение обновлений с какой-то постоянной частотой и… да. Верно, теперь мы пытаемся сделать всё «ПРАВИЛЬНО».
Если такой крошечный фрагмент кода разворачивается в чудовищные математические вычисления, то представьте более сложные паттерны движения, в которых участвует множество взаимодействующих объектов, и тому подобное. Теперь можно чётко увидеть, что «правильное» решение нереализуемо. Максимум, чего мы можем добиться — это «грубое приближение». Давайте пока об этом забудем, и допустим, что у нас и в самом деле есть «действительно корректная» версия функций движения. Здорово, правда?
Вообще-то нет. Вот реальный пример проблемы, которая у меня возникла с этим в Bombernauts. Игрок может подпрыгивать примерно на 1 тайл, а игра разворачивается в сетке из блоков в 1 тайл. Чтобы приземлиться на блок, ноги персонажа должны подняться над верхней поверхностью блока.
Но так как распознавание коллизий здесь выполняется с дискретным шагом, то если игра работает с низкой частотой кадров, иногда ноги не будут достигать поверхности тайла, хоть они и следовали по той же кривой движения, и вместо подъёма игрок будет соскальзывать со стены.
Очевидно, что эта проблема решаема. Но она иллюстрирует виды проблем, с которыми мы сталкиваемся при попытке правильной реализации работы игрового цикла с переменным шагом времени. Мы теряем согласованность и детерминированность, поэтому придётся избавиться от функций реплея игры по записи ввода игрока, детерминированного мультиплеера и того подобного. Для основанной на рефлексах быстрой 2D-игры согласованность чрезвычайно важна (и снова привет спидраннерам).
Если вы попытаетесь отрегулировать шаги времени так, чтобы они не были ни слишком большими, ни слишком маленькими, то лишитесь основного преимущества, получаемого от переменного шага времени, и спокойно можете использовать два других описанных здесь метода. Овчинка не будет стоить выделки. Слишком много лишних усилий будет вложено в игровую логику (реализация правильной математики движения), и потребуется слишком много жертв в области детерминированности и согласованности. Я бы использовал этот метод только для музыкальной ритм-игры (в которой уравнения движения просты и требуется максимальная отзывчивость и плавность). Во всех других случаях я выберу фиксированное обновление.
Теперь вы знаете, как заставить игру работать с постоянной частотой 60fps. Это тривиально просто, и больше ни у кого с этим не должно возникать проблем. Больше нет никаких других проблем, усложняющих эту задачу.
Источник: habr.com
Как в hearthstone сделать 60 фпс
Будь в курсе последних новостей из мира гаджетов и технологий
iGuides для смартфонов Apple
Как убрать ограничение в 60 fps в играх в Windows 10
Егор Морозов — 19 июня 2017, 12:50
Некоторые пользователи Windows, обновившиеся до 10ки, могли заметить, что если раньше fps в играх мог быть ощутимо выше 60, то теперь есть ограничение на уровне 60.
Чтобы его убрать, нужно зайти в Пуск > Параметры > Игры > Меню игры > Убрать галку на записи игровых клипов. Там же перейдите во вкладку DVR для игр и уберите галку на записи в фоновом режиме (а вообще можете поснимать там абсолютно все галки, если пользуетесь игровой панелью и игровым режимом Windows 10):
Источник: www.iguides.ru
Как повысить ФПС в WOT Blitz
FPS в играх очень важен. В любом шутере или быстрой игре важно, чтобы ФПС был максимальным. Даже если у вас монитор на 60 герц, то иметь 100 FPS и выше — приятный бонус, который гарантирует отсутствие «просадок» и лагов во время игры. Разбираемся, как его повысить.
Оптимизация работы ПК
Первый способ, который позволяет повысить включить повышенный FPS — оптимизация работы системы. Здесь несколько пунктов.
- Разблокировать его. Способ работает с теми ПК, к которым подключен монитор 144 герц и выше. Сработает, если FPS в игре выше 60 (проверяли программами), но хочется больше.
- Заходим в настройки дисплея.
- Дополнительные настройки.
- Внизу выбираем не 60 ггц, а столько, сколько нужно.
Это основа, которую нужно сделать, если ФПС слишком низкий. Теперь переходим к основе оптимизации компьютера для WOT Блиц.
Устанавливаем файл подкачки
Кликаем на Win + R на клавиатуре. У нас открывается окно «Выполнить». Вводим «sysdm.cpl». Открывается окно «Свойства системы». Тут кликаем на «Дополнительно». Теперь на «Быстродействие» и внутри них жмем на «Параметры».
У нас открывается такое окно.
Кликаем на «изменить». Переходим в окно установки файла подкачки. В самом верху окна у вас будет установлен автоматический файл подкачки, определяемый системой. Если он не установлен, то ставим на автоматический выбор файла подкачки. Если доступен диск, где больше памяти, то выбираем его.
Если на системном диске мало места, то убираем галочку с автоматического поиска и ставим внизу на тумблер «По выбору системы». Будет выбран максимум в связи с ограничениями харды.
Обновите драйвера
Независимо от того, какая у вас видеокарта, драйвера нужно обновлять регулярно.
- У вас видеокарта от NVIDIA? Скачайте GeForce Experience. В ней можно установить драйвера, а сама программа будет регулярно вам сообщать о новых дровах.
- У вас видеокарта от AMD? Поставьте программу AMD Software. Она также автоматически будет обновлять драйвера и сообщать о том, когда выходят новые.
Проверка жесткого диска и его чистка
Никогда не оставляйте на рабочем столе тяжеловесные файлы без создания ярлыка на другом жестком диске. Звучит непонятно, правда?
- На диске C всегда должно быть свободно 15% памяти, но не меньше 15 гигабайт.
- Из папок «Загрузки», «Документы», «Изображения» и прочих нужно удалить ненужные файлы. Рабочий стол тоже желательно почистить.
- Если на системном диске установлены игры или программы, постарайтесь перенести их или переустановить на другой диск.
Если системе не хватит места, то тормозить будет всё.
Чистая загрузка
Игроки понимают под этим словосочетанием два вида загрузки:
- Который делается через конфиг системы. Все программы отключаются, чтобы проверить, что именно влияет на работу системы.
- Во время запуска игры отключается всё, что может быть не нужно. Об этом и поговорим.
В World of Tank есть понятие загруженности. Когда игра забирает слишком много ресурсов системы. Для того, чтобы сделать чистую загрузку, мы:
- Перед запуском ВОТ Блиц отключаем все ненужные программы: браузер, дискорд (если не используем), проверяем, чтобы в Steam параллельно ничего не скачивалось. Отключаем игровые центры.
- После запуска игры проверяем, какие процессы потребляют много оперативной памяти. Если они не нужны (и они не системные), тоже отключаем.
Что делать, если ничего не помогло
Несмотря на то, что WOT Blitz требует очень мало ресурсов ПК, игра всё-таки может тормозить на ПК, которому можно помочь следующими действиями.
Проверяем на вирусы
Вообще, это первое, что можно было сделать, но вирусы находятся очень редко. Воспользуйтесь любым антивирусом, которому доверяете и проведите полную проверку системы. Да, иногда это может занять много времени. Зато вы убедитесь, что игра перестанет лагать, либо убедитесь, что никакого вируса не было.
Чистим ПК изнутри
Кроме замены термопасты ПК нуждается в том, чтобы сделать ему unlock от пыли, которая скопилась за несколько месяцев или, в худшем случае, лет. Регулярно чистить компьютер — значит улучшать качество игры, повышать FPS и заботится о технике. Рекомендуем отнести компьютер мастеру, если вы не умеете собирать/разбирать компьютер. Это придется сделать во время чистки.
Отключаем оверлеи в Steam и Discord
Если Дискорд вам очень важен и его нужно включить во время игры, то хотя бы выключите его оверлей. Он потребляет много оперативной памяти. Также, как и в стиме.
Его легко найти в настройках самого Steam.
Чистим кэш
Кэширование данных происходит постоянно. Рано или поздно они начинают занимать слишком много места.
- Steam.
- Загрузки.
- Внизу «Очистить кэш загрузки».
Играем на «чистом ПК»
Когда все действия для повышения ФПС в Ворлд оф Танк Блиц были выполнены, то последнее, за чем стоит следить: это чистая загрузка.
- Убираем программы из автозапуска.
- Выключаем ненужные во время игры.
- Чистим свой ПК внутри и на жестком диске.
- Стараемся не устанавливать лишний раз ненужные файлы на системный диск.
Как сделать 120 ФПС в WOT Blitz
На ПК в Steam эта настройка недоступна, поскольку она работает только на телефоне. А на смартфоне можно зайти в настройки и выбрать соответствующий пункт в меню. Если его невозможно активировать тумблером, то он либо недоступен в данный момент (в том числе из-за последнего обновления), либо из-за того, что телефон не поддерживает данную функцию.
Источник: 1lag.com