Ru/Thinking: Difference between revisions
Line 144: | Line 144: | ||
* Визуальные эффекты / партиклы | * Визуальные эффекты / партиклы | ||
* VGUI экран взаимодействия | * VGUI экран взаимодействия | ||
* Изменение скорости игрока (выполняется на стороне клиента, а также серверов, для избежания [[Working_With_Prediction:ru|прогнозируемых]] | * Изменение скорости игрока (выполняется на стороне клиента, а также серверов, для избежания [[Working_With_Prediction:ru|прогнозируемых]] ошибок) | ||
* Ноги страйдеров, привязки веревки (изначально отключено) | * Ноги страйдеров, привязки веревки (изначально отключено) | ||
Revision as of 03:36, 26 July 2013
Think
(обновление) позволяет Entity (энтити) объекту планировать запуск кода в определенное время. Think
может работать постоянно, что позволяет создавать автономные энтити объекты.
Планирование
Функция SetNextThink()
настраивает следующий момент обновления энтити. Принимает значения float (число с плавающей запятой)
void CMyEntity::Spawn()
{
BaseClass::Spawn();
SetNextThink( gpGlobals->curtime ); // Запустить Think прямо сейчас (обновить)
}
void CMyEntity::Think()
{
BaseClass::Think(); // Всегда пишите это здесь, если хотите предопределить функцию Think()
Msg( "Я думаю, следовательно, я существую.\n" );
SetNextThink( gpGlobals->curtime + 1 ); // Обновить еще раз, через 1 секунду
}
Данный код, после создания энтити, каждую секунду выводит сообщение.
Не забывайте использовать gpGlobals->curtime
, чтобы задать следующее время обновления относительно текущего времени, после которого была запущена функция Think
, иначе может начаться бесконечный цикл.
Создание собственных Think функций
Энтити может иметь любое количество дополнительных Think
функций. Чтобы создать (зарегистрировать) еще одну функцию:
- Создайте свою функцию типа
void
. - Добавьте ее в энтити DATADESC с помощью
DEFINE_THINKFUNC()
. - Вызовите
SetThink()
и укажите ссылку на вашу функциюThink
(пример внизу). - Проверьте наличие
DECLARE_DATADESC();
в вашем классе.
BEGIN_DATADESC( CMyEntity )
DEFINE_THINKFUNC( MyThink ), // Регистрация новой Think функции
END_DATADESC()
void CMyEntity::Spawn()
{
BaseClass::Spawn();
SetThink( &CMyEntity::MyThink ); // Задать Think указатель на функцию MyThink()
SetNextThink(gpGlobals->curtime);
}
void CMyEntity::MyThink()
{
Msg( "Я думаю, следовательно, я существую.\n" );
SetNextThink( gpGlobals->curtime + 1 );
}
Разделив ваш код на определенные Think
функции можно легко переключаться между режимами работы вашей энтити.
Использование контекстов
Можно запланировать (запустить) одновременно несколько Think
функций с помощью "think contexts" (контексты). Чтобы создать новый контекст:
- Вызовите
RegisterThinkContext(string ContextName)
указав контекст (название) кThink
функции. - Вызовите
SetContextThink(void* Function, float NextThinkTime, string ContextName) укажите функцию которая будет вызвана контекстом и название вашего контекста
- Для последующих вызовов
Think
, используйтеSetNextThink(float NextThinkTime, string ContextName)
BEGIN_DATADESC( CMyEntity )
DEFINE_THINKFUNC( ContextThink ),
END_DATADESC()
void CMyEntity::Spawn()
{
SetNextThink( gpGlobals->curtime ); // Запуск обычного Think - контекста нет
RegisterThinkContext( "TestContext" );
SetContextThink( &CMyEntity::ContextThink, gpGlobals->curtime, "TestContext" );
}
void CMyEntity::Think()
{
BaseClass::Think();
Msg( "Обновление\n" );
SetNextThink( gpGlobals->curtime + .1 );
}
void CMyEntity::ContextThink()
{
Msg( "Контекстное обновление\n" );
SetNextThink(gpGlobals->curtime + .2, "TestContext" );
}
Это создаст два Think
цикла, оба будут выводить определенные сообщения.
Время
Вот некоторые функции определения времени обновления:
float GetLastThink() // время последнего обновления
float GetNextThink() // следующего обновления
int GetLastThinkTick() // тик (10,000,000 тик/ 1 секунд) прошлого обновления
int GetNextThinkTick() // будущего обновления
Функции GetLast
полезны для управления скорости, с которой что-то происходит.
Это код Think
энтити npc_barnacle фиксирующий скорость движения языка, при смене частоты обновления:
float dt = gpGlobals->curtime - GetLastThink(); // dt - это "delta time (изменение времени относительно прошлого обновления)"
SetAltitude( m_flAltitude + m_flBarnaclePullSpeed * dt ); // смена высоты языка барнакла
Данный код выполняется когда игрока хватает барнакл. Код делает анимацию языка плавной в отличии от скелетной анимации.
ClientThink() - Обновление клиента
Обновления могут быть обнаружены и со стороны клиента (Client-Side), однако есть ограничения. Для одной энтити доступна лишь одна Think
функция.
void C_MyEntity::ClientThink()
{
Msg( "Не нагружайте эту функцию слишком сильно!\n" );
SetNextClientThink( CLIENT_THINK_ALWAYS ); // Обновлять каждый кадр
}
Некоторый примеры client-side обновления:
- Визуальные эффекты / партиклы
- VGUI экран взаимодействия
- Изменение скорости игрока (выполняется на стороне клиента, а также серверов, для избежания прогнозируемых ошибок)
- Ноги страйдеров, привязки веревки (изначально отключено)
Функция SetNextClientThink()
для запуска ClientThink()
. Принимает два значения:
- CLIENT_THINK_ALWAYS
- Выполнять
Think
функцию после каждого кадра клиента. Используйте с осторожностью! Template:Tip:ru - CLIENT_THINK_NEVER
- Остановка всех
Think
обновлений клиента.