Debugging Techniques
Put all your Hints for Debugging here.
As a programmer, I can only think on UnrealScript stuff, but you should add anything that would help someone to get extra info about the environment, actor behaviour and errors on the fly.
UnrealScript Techniques
Use the Log!
The log is generally the first thing to try when debugging.
It lets you append text to the game's log file. The stuff it writes can be viewed while the game is running, type "showlog" in console to open the log window. To start the game with log window already displayed and in windowed mode start UT2004.exe with " -WINDOWED -LOG" parameters.
It is a native function declared in Object, so it is, in effect, a global function. Its declaration is as follows:
native(231) final static function Log( coerce string S, optional name Tag ); //'S' is your message that you want to appear in the log.
The 'Tag' parameter gives the beginning of your message a more meaningful name (useful for mod developers to differentiate their warning messages).
Log output gives you something like this: "Tag: S", where of course 'Tag' and 'S' are replaced. If 'Tag' is not supplied, "ScriptLog" is used.
Log is saved by default to "/GameName/System/GameName.log" file, ie "UT2004/System/UT2004.log". Attempting to view the log file with external application while the game is still running is not recommended, as sometimes information is not actually saved into the log at the moment that it happens – the order and variables are still preserved, but I believe that the Unreal Engine maintains an internal log in memory and only writes it to disk periodically.
The warn function is essentially the same as log, but there is no "tag" argument. The "tag" of the warn function is always "Warning."
native(232) final static function Warn( coerce string S ); //'S' is your message that you want to appear in the log.
The warn function's output is similar to UT's and UT2003's log warnings.
You can also use the "say" functionality to make your actor "talk" within the level and read the output. This allows for a realtime "log" that you can view in-game, though things written using this will not actually be written to the log file:
Level.Game.Broadcast(self, "blah blah blah", 'Say');
OverloadUT: Unfortunately, this method has limited reliability, because the messages broadcasted will be spam filtered just like normal chat. Meaning that if you send too many messages too fast, some of them simply won't be displayed. The limit is quite low too... So be sure you're only sending one message at a time, and only at key times. I like to instead use the ClientMessage() function inside PlayerController - but unfortunately it's a more annoying because you need a specific PlayerController to send it to.
Kirk: Also note that if you suddenly see messages coming up you didn't instigate... it's probably form the bots doing the same thing as you.
Using DisplayDebug (UT2003)
The DisplayDebug function in class Actor shows a lot of info about the player/zone/weapon. It is shown when you use the ShowDebug console command and it can be used to draw pertinent information on the HUD in realtime. If you want to make it compatible with other DisplayDebug functions from other actors, you must insert a carriage return at the end of whatever you are writing, to prevent other actors from appending text directly to whatever you have written.
simulated function DisplayDebug(Canvas Canvas, out float YL, out float YPos) { local string T; super.DisplayDebug(Canvas, YL, YPos); T = "DOT: "$vect(0,0,1) Dot Normal(vector(rotation)); Canvas.DrawText(T,false); YPos += YL; Canvas.SetPos(4,YPos); }
You can also use DisplayDebug to draw anything you normally could to the Canvas. Here is an example of drawing the position of a vector onto the screen visually. The example draws a cross at the on-screen location where the vector would be percieved to be - note that this assumes that the vector is a "location" vector, as it will be drawn relative to the world origin:
simulated function DisplayDebug(Canvas Canvas, out float YL, out float YPos) { Super.DisplayDebug(Canvas, YL, YPos); Canvas.SetDrawColor(255,255,255); Canvas.SetPos(Canvas.WorldToScreen(YOURVECTORHERE).X,Canvas.WorldToScreen(YOURVECTORHERE).Y); DrawCross(Canvas); Canvas.DrawText("A SHORT DESCRIPTION WHICH WILL GET DRAWN NEXT TO THE CROSS GOES HERE",false); Canvas.SetPos(4,YPos); } function DrawCross(canvas c) { c.DrawLine(0, 18); c.DrawLine(1, 18); c.DrawLine(2, 18); c.DrawLine(3, 18); }
Using the Graph (UT2003)
The graph is a debugging method only availible from KVehicle and its subclasses. It is defined in KVehicle. It can be displayed with the Graph Show
console command. To plot a value on the graph, call the GraphData function, as follows:
GraphData("description", var);
Where var (float or int) is your variable and description is any string. The graph automatically adjusts the vertical scale to fit all of the values that have been fed into it. The graph will update whenever a new point is plotted, regardless of what actor plots it. The graph is color coded, and points are joined together based on their descriptions. There is a legend with the graph that will indicate which color is associated with which description and the maximum value that has been plotted for that description.
The Debug Line (UT2003)
DrawDebugLine( Location1, Location2, R, G, B);
This is a great way of showing vectors. It draws a line between the two vectors specified in Location1 and Location2. Technically one is the start and the other is the end, but it doesn't make any visual difference. R, G, and B, are the elements of the color of the line, red, green and blue, respectively. They must each be between 0 and 255. This is superior to just drawing something on the canvas, as it will go "through" objects instead of being drawn on top of them. This makes it much easier to see the actual vector that is being expressed. It is, however, relatively slow. It is not slow in the sense that it will drag down your framerate while you debug, but it is too slow to be reasonably used for in-game effects like a laser. This function can be called at any time and will be "stored up" by the engine until the next frame is drawn. You can draw as many debug lines as you like and they will all be "saved up" in this manner. This can be very useful for, for instance, making a line drawing of the path a bot intends to follow, etcetera.
Staying Debug Line
Another debug line command similar to the one above creates a permanent line, which can be used for easily creating non-dynamic lines in 3D space. This can be handy for displaying the path that a wandering or searching character has taken over time. -ymalaika
DrawStayingDebugLine( Location1, Location2, R, G, B); ClearStayingDebugLines()
Using TextToSpeech (UT2004/UT2003?)
native function TextToSpeech( string Text, float Volume ); //Text: Text you want to be turned into speech
This function is declared in Actor so any actor can use it. An example of how to use it would be to find out if a function was fired or not. It's very useful for those who don't want to go into the log all the time and would like voice confirmation.
Seabreeze: what does the 'Volume' variable represent?
Wormbo: The same thing it represents in any audio function – how loud you want the output to be.
Seabreeze: ahhh.. newbie here! for some reason I was only thinking of volume of objects and not volume of sound, thanks!
Slowing things down
If you need time to set a particular situation up, use one of these [console command]?s:
- playersonly : freezes all movement except you
- slomo #, or set engine.gameinfo gamespeed <value here>
Network Debugging
Testing in a Client/Server Environment
It is crucial that you test your code under client/server conditions. Just running a "listen server" (a network server started from within the game) won't help there; for concerns like replication the listen server behaves just like a standalone game as far as the local player is concerned.
You don't need a LAN or an Internet connection to test your code under networking conditions though: you can Launch A Local Netgame.
ServerPackages
None of your client-side actors will show up or execute client-side code unless your package is loaded client-side; unless that happens to happen anyway (because you're coding a game type, for example), you'll have to add your code package to the server .ini file's ServerPackages
list.
Open the server's .ini file (usually server.ini or, on a local dedicated server, frequently just the game ini file), look for the [Engine.GameEngine]
section and add a line for your package:
ServerPackages=MyPackage
Simulating Lag and Packet Loss
You can tell the engine to simulate network lag, packet loss, packets out of order and packet duplicating when testing on a local server as described above.
Add one or several of the following parameters to the server's command line:
- pktlag=<milliseconds>
- Simulates lag.
- pktloss=<percentage>
- Simulates packet loss. The given percentage specifies how many packets are lost; it can be between 0 (no packet loss) and 100 (all packets will be lost).
- pktdup=<percentage>
- Simulates packet duplication. The given percentage specifies how many packets are duplicated; it can be between 0 (no packet duplication) and 100 (all packets duplicated).
- pktorder=<0 or 1>
- Simulates packets that are received out of order.
A server for a test game with 150 milliseconds lag, 10 percent packet loss and packets out of order would look like this:
ucc server DM-Gael pktlag=150 pktloss=10 pktorder=1
Console Commands
See Console Commands/Debugging Console Commands
A Note about Debugging
It's important to remember that not only can software develop bugs, but your debugging tools themselves can have bugs too. Log and other native debugging commands seem quite stable, but things in DisplayDebug and similar functions are prone to error like any other program. If your debugging tools show that your code is acting in an absolutely bizarre fashion, check your debugging code to see if it is in fact the debugger that is faulty.
Optimizing
If your mod runs slowly or causes hitches on some computers, see Code Optimization.
Related Topics
- Log Warnings
- A Bug's Life
- Spectate Bots
- Testing Botplay
- UDebugger
- Running A Dedicated Server With UCC
- Testing Lab
Discussion
Ch3z I actually run a copy of the 436 server only disto from a seperate folder and connect to it with my reg UT installation. That way I know I'm actually connecting via the internet, and with all the hops to get back to my own machine I get plenty of non-simulated lag. I just feel like its a better test. I also make sure none of the files i need to join the server are in my UT dir and it makes me download them all from the server before connecting. Seems more like a valid test to me. I'm wondering if this would be a good idea or not. Not sure if this is where the page should be created from or not but... check out the Testing Lab.
Shouldn't this page, Debugging Techniques be Category Tutorial?
Tarquin: Not really.
Vitaloverdose is none of this relevant to 2004?
Wormbo: There's a section about additional techniques in UT2004, and of course they apply to UT2004 as well.
OlympusMons: Found the clear debug staying lines thing on the udn just thought I would add it here, not sure if its in the right spot.
Shambler: A class I made to spew debug logs onto the HUD instead of into the log file: Log Interaction