Friday, October 21, 2011

Implementing Your Custom Game

In order to start creating custom logic for your game, you'll have to define "game modes". A single game can have multiple different game modes and each one will be a different class. For example, in a first person shooter, there may be 'Capture the Flag', 'Deathmatch', 'Team Deathmatch', etc. Each one of these will be an implementation of a custom UnrealScript class derived from 'GameInfo'.


class PlaygroundGame extends GameInfo;


event PostLogin( PlayerController NewPlayer )
{
super.PostLogin( NewPlayer );

NewPlayer.ClientMessage( "PlaygroundGame: Welcome " $ NewPlayer.PlayerReplicationInfo.PlayerName);
}


defaultproperties
{
}


This simply defines our own GameInfo class where we can host all the logic that determines the rules of our current game mode.

In the sample above, we've overridden the PostLogin event which gets called whenever a new player joins the game. We send that player a message that shows up on screen so that we know everything is working.

Take a moment and compile your scripts now. This will enable the editor to see our game mode so that we can try it out. Once scripts are done compiling, and no errors occurred, we're ready to try out our new game mode.

There are actually 2 ways to do this. The first, which is more manual, is to define the game type on a per-map basis. Go ahead and launch the editor and leave the default map open. Click on View->World Properties. This launches a properties panel that displays all of the available options for this map.

Expand the GameType panel and you'll see something that looks like the following:


This is where we can define the GameInfo class to use for this map. You have two options. The first is to change the 'Default Game Type' which will determine the GameInfo class to use when the game is launched regularly. The other option 'Game Type for PIE' is the GameInfo class that will be used when you Play In Editor (PIE). For now, we'll assign both of them to new 'PlaygroundGame' class.




If you launch your game now, you'll see our custom message displayed to the user.



The second way to setup a game type is to assign a 'default' globally. That is, all maps, when no game type is specified, will use this setting as its default. Right now, it is assigned to UDKGame.SimpleGame but we'll modify that so it now uses our custom GameInfo class.

Make sure the editor and the game aren't running. This is a MUST when you are editing INI files are their settings won't take effect until the next time you run.

Open up DefaultGame.ini from inside the UDKGame\Config directory and search for the [Engine.GameInfo] section.



We want to overwrite the DefaultGame and DefaultServerGame with our own custom game type. In this case, our package is named 'Playground' and the GameInfo derived class is called 'PlaygroundGame'. So we'll specify 'Playground.PlaygroundGame' as our DefaultGame and DefaultServerGame type.



We can now launch any map without having to specify the Game Type in the World Info properties and it will use our game type. In any map, if we do specify the Game Type, that will take priority. This is the method I will be using as my game will only be supporting one main game mode for now. In the future, we can always change it since it can be overridden per map.

Thursday, October 20, 2011

Setting Up Your Own Game

Setting up your own game in UDK is very easy. You can simply start by building off the initial UDK game example that comes with the program.

The first steps towards being able to create your own project scripts are setting up the initial directories.

Create your own subdirectory under 'Development\Src'
- Ex: Development\Src\MyGame

Create a 'Classes' subdirectory inside your game folder
- Ex: Development\Src\MyGame\Classes


The 'Classes' directory will hold all of your UnrealScript (*.uc) files. As far as I know, you cannot create subdirectories in here to organize your files. Instead, separate 'packages' can be created to layer your application. For now, I'll be using a single directory to hold everything.

The second step is to inform the engine that you would like it to start compiling and loading your custom game package. This is controlled through the config files which are stored inside of 'UDKGame\Config'.

Open 'DefaultEngine.ini' and navigate to the [UnrealEd.EditorEngine] section. This controls which packages get loaded. We'll want to add our own game packages to this as they are created. Currently we only have one so we'll add a line to load it:
+EditPackages=MyGame



Now that the engine is aware of our project, we'll have to compile our scripts. We don't have any scripts currently but this step will validate that everything is setup correctly. Open the 'Unreal Frontend' which is available from the Start Menu or run 'Binaries\UnrealFrontend.exe'

Click the 'Script' button at the top and press 'Compile Scripts'



If all goes well, you will see a line similar to the following at the bottom of your log window:
'Warning, Can't find files matching E:\UDK\UDK-2011-09\Binaries\Win32\..\..\Development\Src\MyGame\Classes\*.uc'



You can now start making your own UC classes. Remember to compile scripts each time you make a modification.

Friday, October 7, 2011

Displaying Custom Debug Info

Displaying debug info from your custom classes is very easy inside of UDK. You'll need to implement a custom HUD to help decide what classes will show their debug info on screen.

You'll also have to implement some custom drawing inside of the objects that you want to display. This is made easy with the 'Canvas' class from the engine. You can find lots of examples within UDK of custom DisplayDebug methods so I won't talk about all of the drawing options available.

Once you've got this, you can type 'showdebug turret' in-game on the console (use ~ to bring it up) and you'll see your custom debug display. Of course, you can implement other tags other than 'turret'. You just need to handle it inside of your custom HUD code (shown below).



class MU_AutoTurret extends Pawn;

simulated function DisplayDebug(HUD HUD, out float out_YL, out float out_YPos)
{
local string T;
local Canvas Canvas;

Canvas = HUD.Canvas;

out_YPos += out_YL;

Canvas.SetPos(4, out_YPos);
Canvas.SetDrawColor(255,0,0);

T = "Turret [" $ GetDebugName() $ "]";
Canvas.DrawText(T, FALSE);
out_YPos += out_YL;
Canvas.SetPos(4, out_YPos);

Canvas.SetDrawColor(255,255,255);

Canvas.DrawText("Location:" @ Location @ "Rotation:" @ Rotation, FALSE);
out_YPos += out_YL;
Canvas.SetPos(4,out_YPos);


Canvas.DrawColor.B = 255;
Canvas.DrawText(" STATE:" @ GetStateName(), FALSE);
out_YPos += out_YL;
Canvas.SetPos(4,out_YPos);
}


class UDNHud extends HUD;

function ShowDebugInfo(out float out_YL, out float out_YPos)
{
local MU_AutoTurret Turret;

if( ShouldDisplayDebug( 'Turret' ) )
{
foreach WorldInfo.AllPawns( class'MU_AutoTurret', Turret )
{
Turret.DisplayDebug( self, out_YL, out_YPos );
}
}
else
{
super.ShowDebugInfo( out_YL, out_YPos );
}
}


class UDNGame extends GameInfo;


defaultproperties
{
HUDType=class'UDNHUD'
}