De/Thinking: Difference between revisions

From Valve Developer Community
< De
Jump to navigation Jump to search
No edit summary
(updated language bar. needs a title.)
Line 1: Line 1:
{{otherlang2
{{lang|Thinking}}[[Category:AI:de]][[Category:Functions:de]][[Category:Programming:de]]
|en=Thinking
{{finishtranslation:de}}
|ru=Thinking:ru
}}
'''Think-Funktionen''' erlauben Entities, Code geplant später ausführen zu lassen. Durch das konstante neuplanen eines Thinks, kann eine automatisierte Schleife erzeugt werden, die die Entity autonom macht.
'''Think-Funktionen''' erlauben Entities, Code geplant später ausführen zu lassen. Durch das konstante neuplanen eines Thinks, kann eine automatisierte Schleife erzeugt werden, die die Entity autonom macht.


== Planung ("Scheduling") ==
== Planung („Scheduling“) ==
 
<code>SetNextThink()</code> wird verwendet, um einzustellen, wann der nächste Think einer Entity ausgeführt werden soll. Es nimmt [[float:de|float]]-Werte an.
<code>SetNextThink()</code> wird verwendet, um einzustellen, wann der nächste Think einer Entity ausgeführt werden soll. Es nimmt [[float:de|float]]-Werte an.


Line 25: Line 22:
</source>
</source>


Beachte die Verwendung von <code>[[gpGlobals:de|gpGlobals]]->curtime</code>, um den übergebenen Wert relativ zum ausführungszeitpunkt zu machen.
Beachte die Verwendung von <code>gpGlobals->curtime</code>, um den übergebenen Wert relativ zum ausführungszeitpunkt zu machen.


{{tip:de|<code>SetNextThink(0)</code> oder <code>SetNextThink(null)</code> werden jeden zukünftigen Think abbrechen.}}
{{tip:de|<code>SetNextThink(0)</code> oder <code>SetNextThink(null)</code> werden jeden zukünftigen Think abbrechen.}}


== Neue Think-Funktionen ==
== Neue Think-Funktionen ==
eine Entity kann eine beliebige Anzahl zusätzlicher Think-Funktionen haben. Um eine neue zu registrieren:
eine Entity kann eine beliebige Anzahl zusätzlicher Think-Funktionen haben. Um eine neue zu registrieren:


# Man muss sichergehen, dass die Funktion <code>void</code> ist.
# Man muss sichergehen, dass die Funktion <code>void</code> ist.
# Hinzufügen zur [[DATADESC:de|DATADESC]] der Entity mit <code>DEFINE_THINKFUNC()</code>.
# Hinzufügen zur [[DATADESC:de|DATADESC]] der Entity mit <tt>DEFINE_THINKFUNC()</tt>.
# <code>SetThink()</code> aufrufen und den Pointer zur Funktion übergeben (siehe Beispiel unten).
# <code>SetThink()</code> aufrufen und den Pointer zur Funktion übergeben (siehe Beispiel unten).
# Man muss sichergehen, dass <code>DECLARE_DATADESC();</code> in der eigenen Klasse ist.
# Man muss sichergehen, dass <code>DECLARE_DATADESC();</code> in der eigenen Klasse ist.
Line 58: Line 54:


Der Think-Code einer Entity kann in verschiedene Funktionen aufgeteilt werden, um es wechseln zwischen dem Operationsmodi zu vereinfachen.
Der Think-Code einer Entity kann in verschiedene Funktionen aufgeteilt werden, um es wechseln zwischen dem Operationsmodi zu vereinfachen.
{{tip:de|<code>SetThink()</code> kann auch aus einer Think-Funktion heraus aufgerufen werden. Der nächste Aufruf wird dann an die neue Funktion gehen.}}
{{tip:de|<code>SetThink()</code> kann auch aus einer Think-Funktion heraus aufgerufen werden. Der nächste Aufruf wird dann an die neue Funktion gehen.}}


== Kontexte verwenden ==
== Kontexte verwenden ==
 
Es ist möglich, eine beliebige Anzahl an Think-Funktionen mit einem „Think-Kontext“ Seite an Seite zu planen. Um einen neuen Kontext zu erzeugen:
Es ist möglich, eine beliebige Anzahl an Think-Funktionen mit einem "Think-Kontext" Seite an Seite zu planen. Um einen neuen Kontext zu erzeugen:


# <code>RegisterThinkContext([[string]] ContextName)</code> aufrufen
# <code>RegisterThinkContext([[string]] ContextName)</code> aufrufen
Line 98: Line 92:


Dies erzeugt 2 gleichzeitige Think-Schleifen, die beide mit unterschiedlicher Rate Konsolenausgaben machen.
Dies erzeugt 2 gleichzeitige Think-Schleifen, die beide mit unterschiedlicher Rate Konsolenausgaben machen.
{{tip:de|Einen neuen Kontext zu erzeugen ist ein großartiger weg, den Funktionsaufruf zu verzögern, ohne die Think-Schleife umwerfen zu müssen.}}
{{tip:de|Einen neuen Kontext zu erzeugen ist ein großartiger weg, den Funktionsaufruf zu verzögern, ohne die Think-Schleife umwerfen zu müssen.}}


== Utilities ==
== Utilities ==
Diese sollten selbsterklärend sein:
Diese sollten selbsterklärend sein:


Line 115: Line 107:


Die <code>GetLast</code>-Funktionen sind nützlich für die Kontrolle der Rate, in der etwas auftritt.  
Die <code>GetLast</code>-Funktionen sind nützlich für die Kontrolle der Rate, in der etwas auftritt.  
Dieser Think-Code des [[npc_barnacle:de|npc_barnacle]] moduliert die Deschwindigkeit der Zungenbewegung, auch wenn die Think-Häufigkeit sich ändert:
Dieser Think-Code des {{ent:de|npc_barnacle}} moduliert die Deschwindigkeit der Zungenbewegung, auch wenn die Think-Häufigkeit sich ändert:


<source lang=cpp>
<source lang=cpp>
Line 124: Line 116:
Damit diese nicht-[[skeletal:de|Skelett]]-Animation weich ist, muss der Code jeden Frame ausgeführt werden. Genau das Passiert, bis das Barnacle nicht mehr in der [[PVS:de|PVS]] des Spieler ist, wonach die Rate verringert wird – wofür der obige Code nötig ist.
Damit diese nicht-[[skeletal:de|Skelett]]-Animation weich ist, muss der Code jeden Frame ausgeführt werden. Genau das Passiert, bis das Barnacle nicht mehr in der [[PVS:de|PVS]] des Spieler ist, wonach die Rate verringert wird – wofür der obige Code nötig ist.


== ClientThink() ==
==<tt>ClientThink()</tt>==
 
Think kann ebenfalls auf der Clientseite auftreten, aber dessen Auswirkungen sind limitiert. Nur eine Think-Funktion wird für jede Entity unterstützt.
Think kann ebenfalls auf der Clientseite auftreten, aber dessen Auswirkungen sind limitiert. Nur eine Think-Funktion wird für jede Entity unterstützt.


Line 143: Line 134:
<code>SetNextClientThink()</code> wird zum Planen von <code>ClientThink()</code> verwendet. Es gibt 2 spezielle, akzeptierte Werte:
<code>SetNextClientThink()</code> wird zum Planen von <code>ClientThink()</code> verwendet. Es gibt 2 spezielle, akzeptierte Werte:


; CLIENT_THINK_ALWAYS
; <tt>CLIENT_THINK_ALWAYS</tt>
: Think auf Clientseite bei jedem Frame. Mit Vorsicht verwenden! {{tip:de|Man kann <code>[[gpGlobals]]->frametime</code> zur Regulierung der Geschwindigkeit verwenden.}}
: Think auf Clientseite bei jedem Frame. Mit Vorsicht verwenden! {{tip:de|Man kann <code>gpGlobals->frametime</code> zur Regulierung der Geschwindigkeit verwenden.}}
; CLIENT_THINK_NEVER
; <tt>CLIENT_THINK_NEVER</tt>
: Pausiert automatisch alle Client-Thinks.
: Pausiert automatisch alle Client-Thinks.
[[Category:Programming:de]]
[[Category:AI:de]]
[[Category:Functions:de]]

Revision as of 16:13, 31 May 2022

English (en)Deutsch (de)Español (es)Português do Brasil (pt-br)Русский (ru)Translate (Translate)

Template:Finishtranslation:de Think-Funktionen erlauben Entities, Code geplant später ausführen zu lassen. Durch das konstante neuplanen eines Thinks, kann eine automatisierte Schleife erzeugt werden, die die Entity autonom macht.

Planung („Scheduling“)

SetNextThink() wird verwendet, um einzustellen, wann der nächste Think einer Entity ausgeführt werden soll. Es nimmt float-Werte an.

void CMyEntity::Spawn()
{
	BaseClass::Spawn();
	SetNextThink( gpGlobals->curtime ); // Think jetzt
}

void CMyEntity::Think()
{
	BaseClass::Think(); // Das muss immer gemacht werden, wenn Think() überschrieben wird

	Msg( "Ich denke, also bin ich.\n" );
	SetNextThink( gpGlobals->curtime + 1 ); // Think in 1 Sekunde nochmal
}

Beachte die Verwendung von gpGlobals->curtime, um den übergebenen Wert relativ zum ausführungszeitpunkt zu machen.

Template:Tip:de

Neue Think-Funktionen

eine Entity kann eine beliebige Anzahl zusätzlicher Think-Funktionen haben. Um eine neue zu registrieren:

  1. Man muss sichergehen, dass die Funktion void ist.
  2. Hinzufügen zur DATADESC der Entity mit DEFINE_THINKFUNC().
  3. SetThink() aufrufen und den Pointer zur Funktion übergeben (siehe Beispiel unten).
  4. Man muss sichergehen, dass DECLARE_DATADESC(); in der eigenen Klasse ist.
BEGIN_DATADESC( CMyEntity )
	DEFINE_THINKFUNC( MyThink ), // Die neue Think-Funktion registrieren
END_DATADESC()

void CMyEntity::Spawn()
{
	BaseClass::Spawn();
	SetThink( &CMyEntity::MyThink ); // Einen Funktionszeiger übergeben
	SetNextThink(gpGlobals->curtime);
}

void CMyEntity::MyThink()
{
	Msg( "Ich denke, also bin ich.\n" );
	SetNextThink( gpGlobals->curtime + 1 );
}

Der Think-Code einer Entity kann in verschiedene Funktionen aufgeteilt werden, um es wechseln zwischen dem Operationsmodi zu vereinfachen. Template:Tip:de

Kontexte verwenden

Es ist möglich, eine beliebige Anzahl an Think-Funktionen mit einem „Think-Kontext“ Seite an Seite zu planen. Um einen neuen Kontext zu erzeugen:

  1. RegisterThinkContext(string ContextName) aufrufen
  2. SetContextThink(void* Function, float NextThinkTime, string ContextName) aufrufen
  3. SetNextThink(float NextThinkTime, string ContextName) für nachfolgende Thinks aufrufen
BEGIN_DATADESC( CMyEntity )
	DEFINE_THINKFUNC( ContextThink ),
END_DATADESC()

void CMyEntity::Spawn()
{
	SetNextThink( gpGlobals->curtime ); // Standard Think-Schleife - kein Kontext
	
	RegisterThinkContext( "TestContext" );
	SetContextThink( &CMyEntity::ContextThink, gpGlobals->curtime, "TestContext" );
}

void CMyEntity::Think()
{
	BaseClass::Think();

	Msg( "Think\n" );
	SetNextThink( gpGlobals->curtime + .1 );
}

void CMyEntity::ContextThink()
{
	Msg( "Kontext-Think\n" );
	SetNextThink(gpGlobals->curtime + .2, "TestContext" );
}

Dies erzeugt 2 gleichzeitige Think-Schleifen, die beide mit unterschiedlicher Rate Konsolenausgaben machen. Template:Tip:de

Utilities

Diese sollten selbsterklärend sein:

float	GetLastThink()
float	GetNextThink()
int	GetLastThinkTick()
int	GetNextThinkTick()
Barnacle.jpg

Die GetLast-Funktionen sind nützlich für die Kontrolle der Rate, in der etwas auftritt. Dieser Think-Code des npc_barnacle moduliert die Deschwindigkeit der Zungenbewegung, auch wenn die Think-Häufigkeit sich ändert:

float dt = gpGlobals->curtime - GetLastThink(); // dt ist "delta time" ("Zeitunterschied")
SetAltitude( m_flAltitude + m_flBarnaclePullSpeed * dt ); // Ändern der Zungenhöhe

Damit diese nicht-Skelett-Animation weich ist, muss der Code jeden Frame ausgeführt werden. Genau das Passiert, bis das Barnacle nicht mehr in der PVS des Spieler ist, wonach die Rate verringert wird – wofür der obige Code nötig ist.

ClientThink()

Think kann ebenfalls auf der Clientseite auftreten, aber dessen Auswirkungen sind limitiert. Nur eine Think-Funktion wird für jede Entity unterstützt.

void C_MyEntity::ClientThink()
{
	Msg( "Packe nichts teures in diese Funktion!\n" );
	SetNextClientThink( CLIENT_THINK_ALWAYS ); // Think in jedem Frame
}

Ein paar Beispiele für Clientseitige Thinks sind:

  • visuelle Effekte / Partikel
  • VGUI-Interaktionen
  • Anpassung der Spielergeschwindigkeit (auf dem Client und auf dem Server, um Vorhersageprobleme zu vermeiden)
  • Fangseile der Strider (standardmäßig deaktiviert)

SetNextClientThink() wird zum Planen von ClientThink() verwendet. Es gibt 2 spezielle, akzeptierte Werte:

CLIENT_THINK_ALWAYS
Think auf Clientseite bei jedem Frame. Mit Vorsicht verwenden! Template:Tip:de
CLIENT_THINK_NEVER
Pausiert automatisch alle Client-Thinks.