Autor: | Timo Stark (aka Triple-X, Hawkgames) |
Datum: | 18.08.2005 |
Letzte Aktualisierung: | 18.08.2005 |
Tipp: Durch Klicken auf einen Kapitelunterpunkt gelangen Sie sofort zur gewünschten Stelle. Über die Pfeilbuttons gelangen Sie wieder an den Anfang dieses Tutorials.
Hallo
Obwohl der Bereich des Debuggings
gerade in der Programmierung sehr wichtig ist, kennen sich leider nur
wenige Programmierer damit aus, daher werde ich in diesem Tutorial auf
Möglichkeiten des Debugging in C-Script und auf effektive Fehlersuche
in 3DGamestudio eingehen. Zur effektiven Fehlersuche gehören unter
anderem das beseitigen von Engine Fehlern (Empty Pointer, Invalid Array
Index usw.), Syntax Fehlern und Logischen Fehlern. Solche Fehler können
auf Dauer sehr nervtötend und demotivierend sein, allerdings muss man
sich als Programmier darauf einstellen 80% seiner Zeit mit Fehlersuche
zu verbringen.
Für dieses Tutorial sollte man etwas Script-Kenntnis mitbringen, da ich die Beispielscripte nur über Kommentare erklären werde. Falls es Probleme mit den Programmierbeispielen geben sollte, hilft meistens das Handbuch oder ein C-Script Tutorial wie z.B. das C-Script Tutorial für Anfänger.
Viel Spaß beim lesen, TripleX
Unter einem Syntaktischen Fehler versteht man einen Fehler in der Syntax des Scriptes. Der Fehler wird meist von dem C-Script Compiler ausgegeben. Einige typische Syntax Fehler sind z.B. das vergessen eines Semikolons nach einer Anweisung, oder auch ein Verschreibfehler. Syntaktische Fehler sind in der Regel sehr leicht zu beseitigen. Gerade als Anfänger muss man allerdings aufpassen, dass man bei vielen angezeigten Fehlern nicht demotiviert aufgibt sondern Fehler für Fehler beseitigt. Meistens sind die Ausgaben des Compilers nur Folgefehler. Wenn Sie zum Beispiel bei einer Variablendekleration statt var weapon_number, var weapo_number schreiben und im darauf folgenden Script oft auf die deklarierte Variable eingehen, werden Sie sehr viele Fehler bekommen obwohl Sie nur eine Zeile korrektieren müssen.
Grundsätzlich ist deshalb wie gesagt bei Syntaktischen Fehlern zu beachten, dass man Sie der Reinfolge nach abarbeitet. Das heißt Fehler für Fehler.
Hier ist eine typische Compilerausgabe bei einem Syntaktischen Fehler:
Wichtig für einen Programmierer sind folgende Informationen:
<point1a+=1> In Diesen eckigen Klammern steht die Codezeile in der der Fehler auftritt.
weapon_starter.wd 496l Gibt die WDL Datei und die Zeile an in der der Fehler auftritt.
Error(63) Gibt die Fehler Identifikationsnummer an.
Parameter unknown point1a
Da der Programmierer aber meist nur mit der Fehler ID wenig anfangen
kann gibt der Compiler auch noch eine kurze Beschreibung aus.
Noch einmal kurz als Überblick:
< Fehlerhafter Code >
WDL Datei Zeile:0 Error(Identfikationsnummer des Fehlers): Fehlerbeschreibung
Oft reicht es schon die Fehlerbeschreibung und die Zeile des Fehlerauftritts in der Compilerausgabe zu lesen um den Fehler zu beheben. Bei der oberen Fehlermeldung hab ich z.B. nach point einen Doppelpunkt vergessen (um einen goto Point zu definieren). Leider ist dies nicht immer möglich, deshalb werde ich im Folgenden auf die häufigsten Compiler Fehlermeldungen eingehen und typische Fehlerursachen und Lösungsmöglichkeiten erläutern.
Wie in der Fehlerbeschreibung schon angegeben verweist diese Meldung meist auf ein fehlendes Semikolon. Allerdings sollten Sie sich nicht darauf versteifen unbedingt einen Semikolon Fehler zu suchen. Unter Umständen könnte diese Fehlermeldung auch eine vergessene öffnende geschweifte Klammer hinter z.B. einem IF Abgleich bedeuten ( if(test) blub = 1; } ).
Diese Fehlermeldung bedeutet bei der Erweiterung mit "too many assigns" meistens, dass Sie in einer IF/WHILE Anweisung einen Operatorfehler gemacht haben. d.h. beim Vergleich z.B. nur ein "=" statt 2 "=". Bei dem Zusatz "unknown function" haben Sie vermutlich bei einem Funktionsaufruf zu viele oder zu wenige Funktionsparameter übergeben.
Dieser Fehler bedeutet meistens, dass ein Semikolon nach einem Befehl vergessen wurde. In diesem Scriptbeispiel nach a+1. Unter Umständen kann er auch bedeuten, dass vor dem Ende einer WDL Datei vergessen wurde eine geschweifte Klammer zu schließen. ( } )
Diese Fehlermeldung bedeutet am Ende fast das gleiche wie PARAMETER UNKNOWN. Mit den Unterschied, dass sich diese Fehlermeldung meist auf Rechtschreibfehler in Keywords (Keywords sind z.B. var,string,on_esc,on_a-z, entity etc.) bezieht. In diesem Beispiel habe ich z.B. statt on_esc, on_ec geschrieben.
Wie bei dieser Fehlerbeschreibung schon angegeben wird, fehlt eine geschweifte Klammer. Zur Fehlerlösung einfach bei der angegebenen Zeile nach fehlenden geschweiften Klammern suchen und wenn nötig einsetzten.
Zu beachten ist noch, dass diese Funktion sehr viele Folgefehler hervorruft. Diese beachten Sie am besten einfach nicht und folgen dem Grundsatz des Debuggings bei Syntaxfehlern: Fehler für Fehler.
Error 63 ist ein sehr häufig auftretender Fehler. Generell besagt er nur, dass im Script versucht wird auf ein C-Script Objekt (Sound/Variable/View/String usw.) zuzugreifen, das nicht definiert wurde. Zur Fehlerbeseitigung sollte man das entsprechende Parameter (in diesem Fall ammopack_snd) und das, falls vorhanden, definierte Objekt auf Rechtschreibfehler untersuchen. Möglicherweise wurde auch vergessen das notwendige Objekt zu definieren.
Diese Fehlermeldung kann mehrere Ursachen haben.
1) Von der, in der
Fehlermeldung genannten Funktion, wurde ein Prototyp erstellt. Zu
diesem Prototypen wurde allerdings keine Funktion gefunden.
2)
Unter Umständen kann es auch sein, dass in der Funktion VOR der
angegeben Funktion eine geschweifte Klammer nicht geschlossen, oder ein
Semikolon vergessen wurde.
3) Es wird versucht auf eine Funktion zuzugreifen, die nicht vorhanden
ist. Wie immer auf Rechtschreibfehler beim Funktionsaufruf und bei der
Funktionsdefinition überprüfen.
Die Ursache dieser Fehlermeldung ist, dass im Script (Zeilen und WDL Dateien sind wie immer angegeben) auf eine Bitmap zugegriffen werden soll, die nicht definiert wurde. Zur Lösung des Fehlers kontrollieren Sie, ob Sie das jeweilige Bitmap vielleicht definiert haben aber sich bei der Namensgebung verschrieben haben oder wenn nötig definieren Sie das Bitmap neu. ( bmap name <dateiname.dateiart>; )
Diese Fehlermeldung gibt nur an, dass eine im Script includierte/eingebundene Datei (welcher Dateiart auch immer) nicht gefunden werden kann. Falls Sie sicher sind, dass die Datei im Ordner vorhanden ist, überprüfen Sie am besten noch einmal die PATH Angaben und die Rechtschreibung.
Ein Semantischer Fehler tritt auf, wenn das Script zwar startet (also kein Syntaktischer Fehler vorliegt), aber es nicht das macht was Sie wollen (z.B. wollen Sie dem Spieler einen Lebenspunkt hinzufügen, aber das Script gibt dem Gegner den Lebenspunkt). Diese Art von Fehler ist sehr viel schwerer aufzuspüren, auch wenn C-Script Ihnen eine Menge an Möglichkeiten zur Fehlerbeseitigung gibt.
Eine der besten Möglichkeiten zur Beseitigung von Semantischen Fehler ist der Breakpoint (übersetzt "Haltepunkt"). Mit der Hilfe eines Breakpoints können Sie das Script zu einer bestimmten Stelle anhalten und jede C-Script Anweisung (eine DLL können Sie mit breakpoints nicht Debuggen) nacheinander ausführen. Der breakpoint zeigt Ihnen die Rückgabewerte jedes Befehls an. Wozu ist das nützlich?
1) Mit Hilfe eines
breakpoints können Sie zu einer bestimmten Stelle in einem Script den
Wert von Variablen, Skills usw. überprüfen.
2) Durch den breakpoint ist es möglich zu testen, ob eine bestimmte Stelle im Script überhaupt aufgerufen wird.
Einen Breakpoint kann man ganz einfach über ein breakpoint; in der entsprechenden Zeile des Scriptes aufrufen. Ein Beispiel:
|
Testen Sie den breakpoint; einmal. Wenn er aufgerufen wird, hören Sie ein "piepsen" und in der oberen linken Ecke des Engine Fensters erscheint eine Schrift die in etwa so aussieht:
Jetzt ist der Breakpoint-Modus aktiviert. Hier können Sie jetzt jede einzelne Anweisung der Funktion durchgehen -> (temp==32) ist die if Abfrage.
Wenn Sie nun [LEERTASTE] drücken erscheint auf der linken Seite (neben den Pfeil) eine Zahl. Diese Zahl gibt den Rückgabewert der ausgeführten Anweisung wieder (In diesem Beispiel wird 1.000 dort da stehen. Wenn eine IF Abfrage wahr ist gibt Sie 1 zurück, wenn falsch 0).
Zur nächsten Anweisung können Sie nun springen indem Sie wieder [LEERTASTE] drücken. Falls Sie den breakpoint beenden wollen, aber trotzdem spätere breakpoints NICHT ignorieren wollen drücken Sie [STRG] + [LEERTASTE]. Falls Sie den breakpoint beenden, und alle weiteren ignorieren wollen drücken Sie [ESC].
Auch wenn die Bedienung eines Breakpoints nicht leicht erscheint würde ich ihn doch oft nutzen. Mit seiner Hilfe kann man schnell Rückgabewerte und Objektwerte überprüfen.
Da es oft Probleme mit Rückgabewerten gibt ("warum gibt der breakpoint jetzt diese Zahl zurück") hier eine Liste von Rückgabewerten:
Scriptzeile | Rückgabewert |
if(wert1 OPERATOR wert2) | 1 Falls wahr, 0 falls falsch |
while(wert1 OPERATOR wert2) | 1 Falls wahr, 0 falls falsch |
Variable1 = Variable2; | Neuer Wert von Variable1 |
Pointer1 = Pointer2; | Wert des Pointers. Normalerweise nicht zu gebrauchen. |
C-Script Anweisung (str_cmpi / str_cpy usw.) | Siehe Handbuch -> Index -> Befehl -> Rückgabewert |
Als Beispiel: Sie bekommen die Fehlermeldung "Invalid Array Index in .." bei folgendem Code:
|
Sie wollen jetzt das Ergebnis von zeile + spalte*10 überprüfen. Dies machen Sie mit Hilfe eines breakpoints so:
|
Wenn Sie jetzt einmal nach dem breakpoint Aufruf [LEERTASTE] drücken sehen Sie das Ergebnis der Berechnung in der oberen linken Ecke. Diese Art von Ergebnisberechnung ist wegen dem 3. angegeben Rückgabewert in der Tabelle möglich (Variable1 = Variable2).
Breakpoints werden in der Release Version (Published) ignoriert.
Oft wollen Sie breakpoints erst zu bestimmten Bedingungen auslösen. Dies geht mit dem Befehl breakpoint_on(Bedingung); sehr einfach. Ein Beispiel:
|
3D Gamestudio bietet die Möglichkeit alle Aktionen eines Entitys zu beobachten. Watched ist ein Pointer kann also einfach über z.B. watched = my; einem Entity zugewiesen und mit Hilfe von watched = NULL; wieder gelöscht werden. Genau wie bei einem breakpoint; erscheinen nach dem setzten des watched Pointers in der oberen Linken Ecke Informationen über das jeweilige Entity.
Was am Anfang etwas unübersichtlich Aussieht, kann sich nach einigen besseren Blicken als sehr große Hilfe entpuppen. Im folgenden eine Liste (1) = 1. Zeile, 2) = 2. Zeile usw.) was die einzelnen Zahlen und Strings bedeuten.
1) Typ, Handle Nummer, Name
2) Position, Winkel, Skalierung
3) Ambient, albedo, alpha, rgb (Färbung), frame, next_frame, skin
4) Actions die von der Entitiy ausgeführt werden und die Event Funktionen.
5) Material
6) Untergrund unter der Entity, Untergrundoberflächennummer und die Textur.
Dies alles sind eine Menge nützlicher Informationen mit denen Sie viele Fehler herausfinden können. Noch ein Hinweis: Wenn Sie im Spiel [SHFIT]+[F11] drücken können Sie ein beliebiges Entity anklicken. Ab jetzt wird dieses Entity beobachtet.
Wenn Sie die Werte von Strings überprüfen wollen gibt es zwei gute Möglichkeiten.
1) Sie definieren einen Debug Text. Wenn Sie einen String überwachen bzw. überprüfen wollen, schreiben Sie einfach Debug_Txt.string = Der_zu_Ueberwachende_String; Und schon wird der String am Bildschirm angezeigt.
2) Des weiteren können Sie einen String noch in einer Datei ausgeben.
Dazu öffnen Sie einfach eine Datei mit den file_ Befehle von 3D
Gamestudio und schreiben per file_str_write den String hinein.
3) Mit Hilfe des Befehls diag(str); können Sie sehr schnell einen String in die Acklog.txt Datei schreiben.
4) Zu guter letzt können Sie noch Strings sehr schnell per draw_text darstellen.
Die String Ausgabe per Text hat den Vorteil, dass Sie den Inhalt des Strings sofort überprüfen können (auch per breakpoint; ). Zusätzlich ist es auch noch sehr einfach zu programmieren. Folgender Code reicht komplett aus:
|
Mit diesem Code definieren Sie den Text Debug_txt. Wenn Sie jetzt einen String anzeigen wollen schreiben Sie einfach in der betreffenden Codezeile:
|
Wozu ist hier der breakpoint; da? Wenn Sie das Script ausführen und der breakpoint wird aufgerufen, können Sie den String Inhalt zu genau diesen Moment überprüfen. Wenn Sie viele Strings mit dieser Weise überwachen könnte es ohne breakpoint; passieren, dass ein ganz anderer String am Bildschirm angezeigt wird als Sie gerade überwachen wollen. Hört sich kompliziert an? Ist es nicht.. Ein Beispiel:
|
Die Stringausgabe per Datei ist meiner Meinung nach nicht der Stringausgabe per Text vorzuziehen, trotzdem besitzt die Ausgabe per Datei einen großen Vorteil. Und zwar können Sie sich, was vor allem bei großen Strings (> 256 Characters) wichtig ist, den String im Nachhinein in Ruhe anschauen. Deshalb würde ich grade bei größeren Strings die Möglichkeit der Ausgabe in eine Text Datei nicht vergessen. Ein Scriptbeispiel:
|
In Ihrem Savedir Ordner können Sie jetzt die Datei "temp.txt" mit dem entsprechenden Inhalt finden.
Mit Hilfe von diag(string); können Sie schnell und einfach einen String in die Acklog.txt (beachten Sie bitte, dass diese Datei nur erschaffen wird, falls Sie die Engine mit der Startzeilenoption -diag starten) schreiben. Auch wenn der Befehl wirklich einfach ist hier ein Beispiel:
function MaterialSave(str) |
Als letzte sinnvolle Möglichkeit der Stringausgabe zu Debugzwecken gibt es noch draw_text. Mit der Hilfe dieses Befehls können Sie einen String zu einer bestimmten Stelle am Bildschirm anzeigen. Bei draw_text müssen Sie allerdings noch beachten, dass draw_text den String nur für einen Frame auf den Bildschirm darstellt. Also lohnt es sich eine Funktion zu schreiben, die einen String dauerhaft auf dem Bildschirm darstellt:
|
Nun können Sie einen String einfach per draw_debug("der String",X Position,Y Position); auf den Bildschirm schreiben. Der Font mit dem der String dargestellt wird lässt sich übrigens mit Hilfe des Befehls draw_textmode verändern.
Es tritt oft der Fall auf, dass Sie bestimmte Variablen ständig auf den Bildschirm sehen möchten. Hierbei ist es ziemlich unsinnig jeden Frame den Variablenwert mit Hilfe eines breakpoints zu kontrollieren. Hier stellt 3D Gamestudio wesentlich nützlichere Werkzeuge.
1) Per Panel (digits) eine Variable dauerhaft sichtbar machen.
2) Genau wie Strings kann man auch Variablen leicht mit Hilfe des Befehls diag in die Acklog.txt schreiben.
Auch die Möglichkeit des Überwachens von Variablen mit draw_text und das schreiben von Variablen in Dateien sind möglich. Hierauf werde ich allerdings nicht mehr eingehen, da man hier eigentlich genau das gleiche Script wie bei Strings nutzen kann.
Die sinnvollste Überwachungsmethode von Variablen sind sicher Panels. Mit Hilfe eines einfachen Panels können Sie sehr einfach den Wert einer Variable dauerhaft auf den Bildschirm darstellen. Ein Scriptbeispiel für solch ein Panel:
|
Wenn Sie mehr als eine Variable überwachen wollen, fügen Sie dem Panel einfach eine weitere digits Zeile hinzu.
Um eine Variable schnell in eine Datei auszugeben empfiehlt sich auch wieder Diag in Kombination mit str_for_num. Vom Prinzip her funktioniert es genauso wie bei den Strings daher sind wohl keine weiteren Erläuterungen notwendig. Vergessen Sie nicht Ihr Programm mit dem Start-Parameter "-diag" zu starten.
|
Mit Hilfe des Befehls beep; kann man zu einer bestimmten Stelle im Script einen "Piepton" abspielen. Mit Hilfe von beep; lässt sich sehr schnell feststellen ob eine Funktion oder auch ein bestimmter If/While Block aufgerufen wird. Beispiel:
if(Bedingung) |
Als weitere Möglichkeit bietet sich noch die Programmierung eines eigenen Debug Systems an. Solch ein System ist dazu da, bestimmte Werte schnell und übersichtlich (also nicht in unübersichtlichen Text Dateien), meist in eine html Datei, auszugeben. Dieses Debug System sollte Ihnen nach Beendigung des Scriptes eine Datei erstellen in der alle Debug Ausgaben übersichtlich präsentiert werden. Ein Beispiel für eine Solche Ausgabe. Da solch ein Debug System sehr aufwändig zu programmieren ist, biete ich hier ein frei Downloadbares Debug System an.
Ingame-Engine Fehler sind meistens folgen von Semantischen Fehler (durch die Beseitigung des Logischen Fehlers kann man auch meist die Engine Fehler beheben). Es gibt viele Gründe warum Sie auftreten und wie man Sie beheben kann. Grundsätzlich wird zwischen Fehlern und Warnungen unterschieden, wobei nach einem Fehler die Engine beendet werden muss. Hier ist es leider unmöglich eine generelle Hilfestellung zu geben, außer das man sich genau wie bei Syntaktischen Fehlermeldungen, die Fehlerbeschreibung sehr genau durchlesen sollte. Meist kann man so schon den Fehler erkennen.
Hier eine typische Engine Fehler und Warnmeldung:
Wichtig für den Spieleprogrammierer sind folgende Informationen:
1) Der Fehlerindex (Error
E1513 bzw. Malfunction W1503). Geben Sie einfach diese Warnmeldung im
Handbuch bei der Suchfunktion ein und Sie finden eine genauere
Beschreibung des Fehlers.
2) Die Fehlerbeschreibung (crash in, Invalid array Index in)
3) Der Fehlerort ( in (function) main).
4) Die Codezeile in der der Fehler auftritt ( str_cat(@2,2); material_saved[1024] =2 ).
Im Handbuch finden Sie alle Fehler und Warnmeldungen mit entsprechender Erklärung. Da diese Erklärung aber nicht immer ausführlich genug ist, sind im Folgenden die häufigsten Fehler mit Lösungsmöglichkeiten aufgelistet.
Die häufigste Fehlermeldung. Kann unter anderem folgende Ursachen haben:
1) Falsche Übergabe von Parametern an C-Script Funktionen (Variable statt String, Zu viele Parameter usw.)
2) Generell eine Ausführung von "falschen" C-Script Code (Teilung durch 0 usw.)
Diese Fehlermeldung tritt immer dann auf wenn in einem Array/Vektor versucht wird auf ein nicht vorhandenes Array Element zuzugreifen. Falls Sie z.B. einen Array mit 1024 Elementen erstellt haben, erhalten Sie diesen Fehler wenn Sie z.B. versuchen auf das 5000. Element zuzugreifen. Als Lösungsmöglichkeit vergrößern Sie wenn nötig den Array oder kontrollieren Sie ob Sie auch auf das richtige Array Element zugreifen (oft wird mit Variablen berechnet auf welches Array Element zugegriffen wird. Überprüfen sie diese Rechnung, wenn nötig über breakpoint).
Diese Warnung kann meist als harmlos betrachtet werden. Sie tritt auf falls Sie ein Level laden indem ein Entity mit einer nicht definierten Action vorhanden ist. Überprüfen Sie wie immer den Actionnamen auf Rechtschreibfehler, schreiben Sie falls nötig die Action oder löschen Sie die Action des Entitys mit WED.
Ihre 3D Grafikkarte besitzt nicht mehr genug Ressourcen. Starten Sie Ihren PC neu oder melden sich ab und wieder an. Dadurch wird der Grafikkartenspeicher geleert. Falls dies nichts hilft, liegt ein ernsteres Problem vor. Aktualisieren Sie Ihre Grafikkartentreiber und nehmen Sie eine Neuinstallation von DirectX 9.0c vor.
Dieser Fehler tritt auf wenn Sie mehr als 1024 verschiedene Entity Typen in Ihrer Map haben. Entfernen Sie ggf. unnötige Entitys. Ab A6.4 ist dieser Fehler entfernt, also updaten Sie, falls möglich, Ihre Engine-Version. Zu beachten ist, dass wenn Sie LOD benutzen pro Model noch weitere 3 LOD-Modelle reserviert werden (_0 bis _3). Also bleiben dann nur noch 256 Entitiy Typen.
Dieser Fehler tritt auf, wenn mehr Entities in Ihrem Level vorhanden sind als per max_entities angegeben. Als Lösung setzten Sie max_entities einfach auf einen höheren Wert (VOR dem ersten level_load setzten!) oder erhöhen Sie den Nexus (WED -> Map Properties -> Nexus).
Falls dieser Fehler auftritt ist die angegebene Datei nicht in dem Spiel Verzeichnis, oder in einem der PATH Verzeichnissen vorhanden. Normalerweise tritt dieser Fehler beim Level laden (In der Map vorhanden Entities die nicht gefunden werden können) oder beim dynamischen laden von Ressourcen (ent_create,media_play usw. ) auf.
Einer der ernsten Fehler die auftreten können. Mögliche Ursachen sind meistens entweder ein Virus oder eine falsche DLL Anwendung (auf Memory Leaks aufpassen). Scannen Sie mit Hilfe von einem Virenscanner (z.B. Antivir) Ihren Computer ab und installieren Sie 3D Gamestudio neu.
Für alle A6 Benutzer gibt es mit SED noch eine weitere großartige Debug-Hilfe (Ein Hinweis: Falls die Debug-Hilfen im folgenden Kapitel bei Ihnen nicht funktionieren kopieren Sie die Datei Debug.dll aus Ihrem 3D Gamestudio Hauptverzeichnis, in Ihren Plugindir Ordner). Mit Hilfe von SED können Sie sich während der gesamten Laufzeit Ihres Programmes Variablen/Strings/Pointer usw. beobachten, deren Werte verändern und breakpoints setzten.
Im folgenden ein kleiner Überblick über alle möglichen SED Debug Funktionen:
Schauen wir uns zu erst einmal jeden Eintrag im Debug Fenster an:
Eintrag | Funktion |
Syntax Check | Mit Hilfe dieser Funktion können Sie sich die Syntax - Fehlermeldungen beim letzten Engine Start anschauen. |
Test Run | Diese Funktion startet die Engine mit dem aktuellen Projekt. |
Break | Wenn Sie auf diesen Button drücken (nur aktiviert falls die Engine gestartet ist) können Sie Ihr Spiel pausieren. |
Stop Debugging | Beendet die Engine |
Network Debug | Diese Funktion ist zum Debugging eines Netzwerk Scriptes da. Hierauf werde ich in diesem Tutorial allerdings nicht näher eingehen. |
Set current file to run | Mit Hilfe dieses Buttons, setzt SED die aktuell selektierte WDL Datei als Start-WDL (Das heißt, wenn Sie das nächste Mal auf "Test Run" drücken, wird diese WDL Datei gestartet) |
Step Over | Falls ein breakpoint ausgelöst wurde, können Sie mit dieser Funktion zur nächsten Anweisung springen (genau wie [LEERTASTE] bei dem "normalen Scriptbreakpoint"). |
Goto current debug position | Nach dem ausführen dieser Funktion springt SED zu der aktuellen Debug Position. |
Toggle Breakpoint | Mit Hilfe dieser Funktion können Sie breakpoints in SED setzten. Klicken Sie einfach mit der Maus auf die Zeile in der Sie den breakpoint setzten wollen und drücken Sie [F9]. Nun wird die Zeile rot, und die Engine wird an dieser Stelle einen breakpoint ausführen. |
Ignore further breakpoints | Ignoriert alle weiteren breakpoints. Gleiche Funktion wie [ESC] bei einem "normalen breakpoint". |
Add Watch | Fügt eine weitere Variable zur Beobachtung hinzu. Ich werde später genauer auf diese Möglichkeit eingehen. |
Edit Watch | Verändert den Wert der markierten Variable. |
Delete Watch | Löscht die markierte Variable aus der Beobachtungsliste. |
Delete all Watches | Löscht alle Variablen aus der Beobachtungsliste. |
Execute Instruction | Mit Hilfe dieser Funktion können Sie eine C-Script Anweisung ausführen. Funktioniert ähnlich wie execute(string); in C-Script |
Reload FX Materials | Diese Funktion lädt alle per effect_load geladene FX Materials neu. |
Alle Buttons die im Bild nicht anklickbar (grau) sind, werden normal wenn die Engine gestartet wird.
Wie schon gesagt können Sie in SED mit Hilfe so genannter "Watches" ("watch" = beobachten/bewachen) Variablen und Strings beobachten uns sogar verändern. Wie macht man das nun genau? Nun als erstes drückt man auf [Debug -> Add watch]. Nun öffnet sich ein Eingabe Fenster. Hier geben Sie den Namen, der zu beobachtenden Variable (oder auch String) an. Ein Beispiel:
Bestätigen Sie die Eingabe per Klick on "OK". Nun sollte in der unteren Ecke von SED ein Fenster erscheinen (Falls nicht drücken Sie [F8] damit er aufpoppt). Wechsel Sie hier im Index Tab zu "Watch".
Jetzt starten Sie die Engine, und wie Sie sehen werden, ist der angegebene Wert (bei Value) immer genau der Wert der Variable.
Falls Sie sich wundern, dass es bei einer Variable einen X/Y/Z Wert gibt: Nur der X Wert ist entscheidend. Er repräsentatiert den Wert der Variable. Bei Vektoren haben natürlich alle 3 Werte eine Bedeutung.
Weitere Werte können Sie der Watch Liste einfach durch [Rechtsklick in das Watch Fenster -> Add Watch] hinzufügen. Durch [Rechtsklick auf eine bestimmte Variable -> Delete Watch] können Sie die Variable von der Watch Liste entfernen. Durch [Rechtsklick -> Edit] können Sie die/den Variable/String verändern. Also einen neuen Wert eingeben. Dies ist gerade zu Debug Zwecken extrem nützlich.
Vergessen Sie auch nie, dass Sie neben Variablen auch Strings in das Watch Fenster hinzufügen können. Nun wird im Value Fenster statt einer Zahl, der Inhalt des Strings angegeben.
Vom Prinzip her funktionieren Breakpoints in SED genauso wie breakpoints per C-Script. Es gibt nur einige kleine Veränderungen.
1) Sie setzten die Breakpoints per [F9] in einer bestimmten Zeile.
2) Wenn der Breakpoint in der Engine ausgelöst wird, müssen Sie zu SED
wechseln um die Debug Funktionen von SED nutzen zu können.
Wenn der breakpoint ausgelöst wurde, werden die Ergebnisse jeder Anweisung im "Output" Fenster (neben dem "Watch" Fenster) ausgegeben.
Zur nächsten Anweisung können Sie per [F4] springen. Um den breakpoint abzubrechen, und weitere breakpoints zu ignorieren, drücken Sie [Debug -> Ignore further breakpoints].
Als letzte Möglichkeit des Debuggens bietet 3D Gamestudio noch ein Debug Panel mit allen Statistiken über FPS, Speicherverbrauch und so weiter. Auch wenn dieses Debug Panel nicht unbedingt zum entfernen von Script-technischen Fehlern gedacht ist, kann es trotzdem bei der Optimierung von Scripten und Levels helfen.
Während des Spiels kann man das Debug Panel mit [F11] öffnen.
Generelle Werte |
Millisekunden pro Frame für... |
Anzahl an... |
Memoryverbrauch (in Kilobytes) |
Netzwerk |
Bildschirmbreite (Pixel) |
||||
Frames pro Sekunde |
Renderzeit für Level-Geometrie und Himmel |
Entities |
Nexus |
Latency (in ms) |
Kilopolygone (1000) pro Sekunde |
Renderzeit für Entities |
Sichtbare Level und Sky Entities |
Level-Geometrie Videospeicherverbrauch |
Datenrate Bytes pro Sekunde |
Kameraposition (X) |
Renderzeit für Partikel |
Zahl der Partikel |
Shadowmaps Videospeicherverbrauch |
Spitzen-Datenrate Bytes pro Sekunde |
Kameraposition (Y) |
Renderzeit für Portale und Spiegel |
Zahl der laufenden Media-Streams |
Modelle/Sprites/Himmel Videospeicherverbrauch |
Empfangene Bytes pro Sekunde, Reliable Modus |
Kameraposition (Z) |
Renderzeit für panels, texts and screen entities rendering |
Zahl der laufenden Skript-Funktionen |
Bmap/Font Videospeicherverbrauch |
Empfangene Bytes pro Sekunde, Unreliable Modus |
Kamerawinkel (pan) |
Zeit für Bildwechsel und Monitorsynchronisations |
Verfügbarer Videospeicher (eventuell ungenau) |
Packets pro Sekunde unterdrückt |
|
Kamerawinkel (tilt) |
Zeit für Entity-Updates |
|||
Kamerawinkel (roll) |
Zeit für Skriptausführung |
|||
Zeit für Physikausführung |
Welche Werte z.B. bei Ms/Frame nicht übertroffen werden kann man nicht genau sagen. Allerdings erkennt man durch dieses Debug Panel sehr schnell durch welche Teile des Spiels man an meisten FPS verliert. Des Weiteren hier noch ein Zitat von JCL zum Thema Framerate.
The influence of entities on the frame rate should be not too hard to understand:
If an entity is not invisible, it can increase the rendering time. If
it is not passable, it can increase the collision detection and physics
execution time for other moving entites. And if it has an action, it
will increase the overall script execution time. You can see all this
effects in the [F11] panel. Even an entity that is not rendered because
it's hidden behind the camera or a wall, can have a small impact on the
rendering time because it's bounding box is clipped against the
frustrum.
Übersetzt heißt das soviel wie:
Der Einfluss von Entities auf die Framerate sollte nicht zu schwer zu verstehen sein:
Wenn ein entitiy sichtbar ist, kann es die rendering Zeit erhöhen. Wenn es nicht passabel ist erhöht es die Kollisionserkennung und Physik Ausführungs-Zeit für andere, sich bewegende, Entities. Wenn es eine Aktion hat wird es die allgemeine Scriptausführungs Zeit erhöhen. Sie können all diese Effekte im [F11] panel sehen. Selbst wenn ein entity nicht gerendert wird, weil es hinter der Kamera oder hinter einer Wand ist, kann es einen geringen Einfluss auf die Rendering Zeit haben, weil seine Bounding Box gegen das Frustrum geclippt ist.
Mit Hilfe dieser Folgerungen sollten Sie die Millisekunden pro Frame angaben besser verstehen.
Falls Sie sich einmal ganz sicher sind einen Bug in der Engine gefunden zu haben, beachten Sie bitte noch folgende Hinweise:
1) Kontrollieren Sie ob Ihr Bug schon berichtet wurde ( http://www.conitec.net/fixbugs.txt )
2) Ein Bug im Script-Compiler ist extrem
unwahrscheinlich
. Überprüfen Sie lieber noch einmal Ihr Script.
3) Eine ausführliche Fehlerbeschreibung ist entscheidend für einen
guten Bug Report (wann tritt er auf, was passiert (nicht) usw.).
4) Falls möglich versuchen Sie den Fehler in einem einfachen Test
Projekt zu reproduzieren. Falls Ihnen das möglich ist, fügen Sie Ihrem
Post noch eine Anleitung hinzu, wie man den Fehler reproduzieren kann.
5) Bei Hardware Fehlern ist der Acklog noch wichtig. Ihn bekommen
Sie indem Sie Ihr Script mit dem Parameter "-diag" starten
(Hauptverzeichnis -> Acklog.txt)
Wenn sich alle User an diese Grundregeln halten können eventuelle Bugs wesentlich schneller gefunden und entfernt werden.
Ich hoffe, dass Sie durch dieses Tutorial gelernt haben mit Fehlern umzugehen. Bei Fragen über dieses Tutorial bitte bei Triple-X@hawkgames.de oder bei mir unter ICQ: 170911701 melden.
TripleX aka Timo Stark, 18.08.2005