Ru/Thinking: Difference between revisions
No edit summary |
m (obsolete language category) |
||
(10 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
{{ | {{lang|title=Thinking (Обновление)|Thinking}}{{ACategory|AI}}{{ACategory|Functions}}{{ACategory|Programming}} | ||
|title=Thinking (Обновление) | |||
| | |||
| | |||
}} | |||
<code>Think</code> (обновление) позволяет | <code>Think</code> (обновление) позволяет {{L|Entity|Entity (энтити)}} объекту планировать запуск кода в определенное время. <code>Think</code> может работать постоянно, что позволяет создавать автономные энтити объекты. | ||
== Планирование == | == Планирование == | ||
Функция <code>SetNextThink()</code> настраивает следующий момент обновления энтити. Принимает значения [[float|float (число с плавающей запятой)]] {{en}}. | |||
Функция <code>SetNextThink()</code> настраивает следующий момент обновления | |||
<source lang=cpp> | <source lang=cpp> | ||
Line 27: | Line 22: | ||
</source> | </source> | ||
Данный код, после создания | Данный код, после создания энтити, каждую секунду выводит сообщение. | ||
Не забывайте использовать < | Не забывайте использовать <tt>gpGlobals->curtime</tt>, чтобы задать следующее время обновления относительно текущего времени, после которого была запущена функция <tt>Think</tt>, иначе может начаться бесконечный цикл. | ||
{{tip|<code>SetNextThink(0)</code> или <code>SetNextThink(null)</code> остановит любые следующие обновления.}} | |||
{{tip | |||
== Создание собственных Think функций == | == Создание собственных Think функций == | ||
Энтити может иметь любое количество дополнительных <code>Think</code> функций. Чтобы создать (зарегистрировать) еще одну функцию: | |||
# Создайте свою функцию типа <code>void</code>. | # Создайте свою функцию типа <code>void</code>. | ||
# Добавьте ее в | # Добавьте ее в энтити {{L|Data_Descriptions|DATADESC}} с помощью <tt>DEFINE_THINKFUNC()</tt>. | ||
# Вызовите <code>SetThink()</code> и укажите ссылку на вашу функцию <code>Think</code> (пример внизу). | # Вызовите <code>SetThink()</code> и укажите ссылку на вашу функцию <code>Think</code> (пример внизу). | ||
# Проверьте наличие <code>DECLARE_DATADESC();</code> в вашем классе. | # Проверьте наличие <code>DECLARE_DATADESC();</code> в вашем классе. | ||
Line 61: | Line 54: | ||
</source> | </source> | ||
Разделив ваш код на определенные <code>Think</code> функции можно легко переключаться между режимами работы вашей | Разделив ваш код на определенные <code>Think</code> функции можно легко переключаться между режимами работы вашей энтити. | ||
{{tip|<code>SetThink()</code> может быть использована и через саму функцию <code>Think</code>. Следующий вызов обновления будет сделан через новую выбранную функцию.}} | |||
{{tip | |||
== Использование контекстов == | == Использование контекстов == | ||
Можно запланировать (запустить) одновременно несколько <code>Think</code> функций с помощью «think contexts» (контексты). Чтобы создать новый контекст: | |||
# Вызовите <code>RegisterThinkContext({{L|string}} ContextName)</code> указав контекст (название) к <code>Think</code> функции. | |||
# Вызовите <code>SetContextThink({{L|void}}* Function, float NextThinkTime, string ContextName) укажите функцию которая будет вызвана контекстом и название вашего контекста</code> | |||
# Вызовите <code>RegisterThinkContext( | |||
# Вызовите <code>SetContextThink( | |||
# Для последующих вызовов <code>Think</code>, используйте <code>SetNextThink(float NextThinkTime, string ContextName)</code> | # Для последующих вызовов <code>Think</code>, используйте <code>SetNextThink(float NextThinkTime, string ContextName)</code> | ||
Line 102: | Line 93: | ||
Это создаст два <code>Think</code> цикла, оба будут выводить определенные сообщения. | Это создаст два <code>Think</code> цикла, оба будут выводить определенные сообщения. | ||
{{tip|Создать новый контекст — это хороший способ для планирования запуска вашей функции, при котором другие <code>Think</code> функции затронуты не будут.}} | |||
{{tip | |||
== Время == | == Время == | ||
Line 111: | Line 101: | ||
<source lang=cpp> | <source lang=cpp> | ||
float GetLastThink() // время последнего обновления | float GetLastThink() // время последнего обновления | ||
float GetNextThink() // следующего обновления | float GetNextThink() // время следующего обновления | ||
int GetLastThinkTick() // | int GetLastThinkTick() // время прошлого обновления в тиках (10,000,000 тик/ 1 секунд) | ||
int GetNextThinkTick() // будущего обновления | int GetNextThinkTick() // время будущего обновления в тиках | ||
</source> | </source> | ||
Line 119: | Line 109: | ||
Функции <code>GetLast</code> полезны для управления скорости, с которой что-то происходит. | Функции <code>GetLast</code> полезны для управления скорости, с которой что-то происходит. | ||
Это | Это <code>Think</code> код энтити {{ent:ru|npc_barnacle}} фиксирующий скорость движения языка, при смене частоты обновления: | ||
<source lang=cpp> | <source lang=cpp> | ||
Line 128: | Line 118: | ||
Данный код выполняется когда игрока хватает барнакл. Код делает анимацию языка плавной в отличии от скелетной анимации. | Данный код выполняется когда игрока хватает барнакл. Код делает анимацию языка плавной в отличии от скелетной анимации. | ||
== ClientThink() - Обновление клиента == | ==<tt>ClientThink()</tt> - Обновление клиента== | ||
Обновления могут быть объявлены и со стороны клиента («Client-Side»), однако есть ограничения. Для одной энтити доступна лишь одна <code>Think</code> функция. | |||
Обновления могут быть | |||
<source lang=cpp> | <source lang=cpp> | ||
void C_MyEntity::ClientThink() | void C_MyEntity::ClientThink() | ||
{ | { | ||
Msg( "Не | Msg( "Не нагружайте эту функцию слишком сильно!\n" ); | ||
SetNextClientThink( CLIENT_THINK_ALWAYS ); // Обновлять каждый кадр | SetNextClientThink( CLIENT_THINK_ALWAYS ); // Обновлять каждый кадр | ||
} | } | ||
Line 141: | Line 130: | ||
Некоторый примеры client-side обновления: | Некоторый примеры client-side обновления: | ||
* Визуальные эффекты / партиклы | * Визуальные эффекты / партиклы | ||
* VGUI экран взаимодействия | * VGUI экран взаимодействия | ||
* Изменение скорости игрока (выполняется на стороне клиента, а также серверов, для избежания | * Изменение скорости игрока (выполняется на стороне клиента, а также серверов, для избежания {{L|Prediction|прогнозируемых}} ошибок) | ||
* Ноги страйдеров, привязки веревки (изначально отключено) | * Ноги страйдеров, привязки веревки (изначально отключено) | ||
Функция <code>SetNextClientThink()</code> для запуска <code>ClientThink()</code>. Принимает два значения: | Функция <code>SetNextClientThink()</code> для запуска <code>ClientThink()</code>. Принимает два значения: | ||
; CLIENT_THINK_ALWAYS | ; <tt>CLIENT_THINK_ALWAYS</tt>: Выполнять <code>Think</code> функцию после каждого кадра клиента. Используйте с осторожностью! {{tip|Используйте <code>gpGlobals->frametime</code> для регулирования скорости.}} | ||
: | ; <tt>CLIENT_THINK_NEVER</tt>: Остановка всех <code>Think</code> обновлений клиента. | ||
; CLIENT_THINK_NEVER | |||
: Остановка всех <code>Think</code> обновлений клиента. | |||
Latest revision as of 04:07, 22 August 2024
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, иначе может начаться бесконечный цикл.

SetNextThink(0)
или SetNextThink(null)
остановит любые следующие обновления.Создание собственных 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
функции можно легко переключаться между режимами работы вашей энтити.

SetThink()
может быть использована и через саму функцию 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
цикла, оба будут выводить определенные сообщения.

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
функцию после каждого кадра клиента. Используйте с осторожностью!Совет:Используйте
gpGlobals->frametime
для регулирования скорости. - CLIENT_THINK_NEVER
- Остановка всех
Think
обновлений клиента.