Ru/Thinking: Difference between revisions
| mNo edit summary | |||
| (9 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 (число с плавающей запятой)]]. | |||
| Функция <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> | ||
| 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> для регулирования скорости.}} | ||
| : Выполнять <code>Think</code> функцию после каждого кадра клиента. Используйте с осторожностью! {{tip | ; <tt>CLIENT_THINK_NEVER</tt>: Остановка всех <code>Think</code> обновлений клиента. | ||
| ; CLIENT_THINK_NEVER | |||
| : Остановка всех <code>Think</code> обновлений клиента. | |||
Latest revision as of 08:54, 9 October 2025
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обновлений клиента.


























