Legacy:Solid Snake/CreatingPawnsRB Part1

From Unreal Wiki, The Unreal Engine Documentation Site
Jump to navigation Jump to search

Creating your own pawn class - Part 1

Introduction

This is going to be a long tutorial, as this is a fairly large part of Unreal. Keep in mind that, this was solely pursued by me because I wanted to start developing and prototyping with Unreal Engine 3.0. Unreal Tournament 2007 will have its own Pawn classes and so forth, so this is not intended to replace those but rather to allow me (and you) to get a working pawn class in RoboBlitz ... which you can then start prototyping your own mod. This part of the tutorial will mainly talk about code and how things have changed between Unreal Engine 2.x and Unreal Engine 3.x. The AnimTree Editor is a complex beast, and will be explained in Part 2. Part 3 will wrap everything up.

Pawn.uc

The pawn.uc in RoboBlitz when exported is rather skeletal. I would imagine that since this was mainly Epic's code a lot of the source script had to be stripped away for legal reasons. However, it appears that it is largely unchanged and we can assume a lot of things are the same between Unreal Engine 2.x's version with Unreal Engine 3.x's version. There appears to still be a whole bunch of booleans you can set to control certain aspects of the Pawn, and other various things as well. There also appears to be certain relics left over from UT2003/UT2004 as well.

<uscript line> var vector serpentinedir; var float serpentinedist; var float serpentinetime; </uscript>

I guess this could be just due to laziness, but it could be used for other things possibly. Although I am pretty sure this is in reference to the Serpentine level in UT2003. Other than that there does appear to be new functions/events as well, some are to do with Kismet and others are just handling different areas. Have a look in the exported source code yourself and you'll see what I mean. However, scanning the Pawn.uc and Actor.uc, it appears that there are some things really different between Unreal Engine 2.x's implementation and Unreal Engine 3.x's implementation. For a start, there doesn't appear to be anything which controlled the actual rendering of the pawn. In Unreal Engine 2.x you had the almighty DT_DrawType enum, which told the object how to render, and various variables which hold the reference to what to render such as 'Mesh', 'StaticMesh', 'Texture' and so forth. There also doesn't seem to be a lot of things other aspects too, but within the default properties, there appears to be a whole bunch of inline objects being created and assigned to an array called 'Components'.

Components

This is one of the key differences between Unreal Engine 2.x and Unreal Engine 3.x. Unreal Engine 3.x organises a lot of areas into components. This means that rendering, collision, sound and other bits and pieces are all organised by their respective components. In this case, we will look at rendering specifically. If you simply extend Pawn, and create your own subclass with no changes and add it in UnrealED 4.0, all you see if the 'Eagle head' sprite and nothing more. Seems that anything you do, doesn't to do anything. How I figured out how this works was by comparing the Pawn class with Skeletal Mesh Actor class. The Skeletal Mesh Actor class, allows you to add a skeletal mesh into UnrealED 4.0 ... and so this is what I wrote ... which seemed to work just fine.

<uscript line> class xPawn extends Pawn

     placeable;

var(Pawn) const editconst LightEnvironmentComponent LightEnvironment;

defaultproperties {

 Begin Object Class=DynamicLightEnvironmentComponent Name=MyLightEnvironment ObjName=MyLightEnvironment Archetype=DynamicLightEnvironmentComponent'Engine.Default__DynamicLightEnvironmentComponent'
   bEnabled=False
   Name="MyLightEnvironment"
   ObjectArchetype=DynamicLightEnvironmentComponent'Engine.Default__DynamicLightEnvironmentComponent'
 End Object
 LightEnvironment=MyLightEnvironment
 Begin Object Class=SkeletalMeshComponent Name=SkeletalMeshComponent0 ObjName=SkeletalMeshComponent0 Archetype=SkeletalMeshComponent'Engine.Default__SkeletalMeshComponent'
   LightEnvironment=MyLightEnvironment
   CollideActors=True
   BlockZeroExtent=True
   benablefullanimweightbodies=True
   Name="SkeletalMeshComponent0"
   ObjectArchetype=SkeletalMeshComponent'Engine.Default__SkeletalMeshComponent'
 End Object
 Mesh=SkeletalMeshComponent0
 Components(0)=SkeletalMeshComponent0
 Components(3)=MyLightEnvironment
 Name="Default__xPawn"
 ObjectArchetype=Actor'Engine.Default__Pawn'

} </uscript>

Seems to obvious when you read it doesn't it? Its obvious that you would create an inline skeletal mesh component, which of course handles the rendering of the skeletal mesh. Of course, this is obvious now that I've shown you the code and how it all connects together. Anyways, why I used Component[0] and Component[3] is because I wanted to override the parent classes Component array. If you look in there, it looks like this:

<uscript line>

  Components(0)=Sprite
  Components(1)=CollisionCylinder
  Components(2)=Arrow

</uscript>

So, this is the reason why simply extending the Pawn class only presented us initially with the Eagle Head [of Doom?] sprite in UnrealED 4.0. Its because the first component was a sprite rendering one [ahhhh!]. So I overrided that with the skeletal mesh component. This probably means that during the creation of my Pawn that a sprite component does actually get created as well and never used, thus creating a little overhead ... but we will just need to put up with that as Pawn is a really useful class handling all sorts of other things we can't really be bothered with coding all over again. As you can also see, collision is handled by the CollisionCylinder component. There are other forms of collision components as well, such as ones for static mesh components, cube components and so forth but for now we can look into that another day. The Arrow component is the actual arrow you see in UnrealED 4.0 and is never seen in game (mostly because it has the 'HiddenGame' boolean set to true in the class, ArrowComponent). I also added the light component as well, mainly because SkeletalMeshActor also had it as well. Lastly, Pawn already defined the Mesh variable correctly, they just didn't seem to link it up properly. So this is why the inline skeletal mesh component is hooked up that variable.

Graphics?

This is the basic pawn class I created. When I place that in UnrealED 4.0 it puts down a pawn but with no mesh. Which is obvious as I haven't told it what to render. From here, it is mostly UnrealED 4.0 work, and some 3DSMax + Character Studio + ActorX work.

Legacy CreatingYourOwnPawn AnimSetEditor.png

So after a one or two hours I imported all of the animations for one of the characters from UT2003 (They never seemed to release the character source art for UT2004). An early warning for those trying to import than Human Male character set, it seems that they used two different sets of bones for the animations. I am unsure how they managed to import all of them successfully, but you would need to do some serious work to actually get it all to work. Hence why I used the Human Female character set as all the animations worked together. Maybe they used a combination? It also seems that there were some animations in UT2003 not released here ... or something anyways as I don't have the fullset of animations. Oh well, it doesn't really matter anyways.

From here you can add some new lines into your skeletal mesh component default properties section which winds up looking like this.

<uscript line>

 Begin Object Class=SkeletalMeshComponent Name=SkeletalMeshComponent0 ObjName=SkeletalMeshComponent0 Archetype=SkeletalMeshComponent'Engine.Default__SkeletalMeshComponent'
   SkeletalMesh=SkeletalMesh'ProjectXB.SkeletalMesh.HumaleFemaleA'
   AnimSets(0)=AnimSet'ProjectXB.Animation.HumanFemaleAnimSet'
   LightEnvironment=MyLightEnvironment
   CollideActors=True
   BlockZeroExtent=True
   benablefullanimweightbodies=True
   Name="SkeletalMeshComponent0"
   ObjectArchetype=SkeletalMeshComponent'Engine.Default__SkeletalMeshComponent'
 End Object
 Mesh=SkeletalMeshComponent0

</uscript>

And thats it! After you recompile, you can now add your pawn into UnrealED 4.0, and it should create a pawn with that mesh in place like. To get a basic player controller up and running, you can use UT2004's PlayerController class. The pawn + controller scheme seems to be still in place and works in the same way. You create a pawn, then get a controller to possess it.

Conclusion

This concludes part one of this tutorial. Hopefully this tutorial has shown you how to create your own renderable pawn in Unreal Engine 3.x. As again, like my other tutorials, I have skimmed over a lot of the basic details which I believe are well covered by other tutorials either on the Wiki or on the internet. I realize that I have not created a step by step process of doing all those, but have rather pointed out key areas which are new. If any critical parts are missing, please feel free to add it in, or request the information from me. I figured most of this out in around three to four hours of playing with code and a lot of debugging, so I may have assumed too much knowledge. Anyways, I think this covers most things.

Part two will discuss about the ideology and the method of the AnimTree and the AnimTree Editor. This is a very powerful way of adding animation into Unreal Engine 3.0 without getting the programmers too involved in the process. This is an excellent way to move forward as this kind of work you want the animators (who make the animations in 3DSMax/Maya or whatever else) to create how the animations will work ingame. This greatly improves work flow, and it also means that animators can control how their animations are used in game.

Comments

How do you export pawn.uc?

Inside the editor, open the Generic Browser and the Actor Classes tab, select File from the top menubar and click Export All Scripts. This will create a folder with all the .uc files the game uses (and you can view). Pawn.uc should be inside the ..\Engine\classes folder.
Not sure how you can export a single script though...
--Rask 10:24, 9 December 2008 (UTC)