Tuesday, October 2, 2012

Cookbook: UDK artist editable properties

Sooner or late in your development you'll come into phase when you have some game skeleton with a lot of parameters (camera, health, etc.). But how to tweak them without the necessity to update unrealscript (defaultproperties) and recompiling?

There are two approaches you can use. Let's take a closer look:

Instanced objects/actors

Each of your actors (buttons, movable/breakable objects, custom lights) will probably need some variables that are preferably tweakable by artist. Additionally each of there instances needs possibility to have differing values of parameters (imagine your ButtonActor with blue light and specific mesh vs other instance of ButtonActor with no light and different mesh).

This is easily achievable using named variables in unrealscript, syntax is really simple:


   1:  class ButtonActor extends Actor
   2:      ClassGroup(BallPuzzler)
   3:      placeable;
   4:   
   5:  // /** */ specifies comment visible for artist in editor
   6:  /** enables actor movement upon activation */
   7:  //(Game) specifies category for parameter in unreal editor
   8:  var(Game) bool bMove;
   9:   
  10:  /** movement offset from base position */
  11:  var(Game) vector vMoveOffset;
  12:   
  13:  /** sound to play upon activation */
  14:  var (Game) SoundCue activationSound;
  15:   
  16:  var(Light) const LightComponent    LightComponent;

This setup results in parameters being categorized in unreal editor into specified groups (F4 on selected actor):


I recommend to create archetype also for instanced objects to create subtypes (for example blue button, red button, healing button) and then use them to create instances (and edit few parameters per instance if necessary).

Not placeable objects


Ok, above mentioned steps work fine for instanced object that are being placed into game level. But what about objects without physical representation in editor (e.g. camera, controller, HUD, etc.)? Here we can create specific Properties object, that can be archetyped and it's parameters updated in content browser.


   1:  class BallPuzzlerProperties extends Object
   2:      HideCategories(Object);
   3:   
   4:  /** min distance from camera */
   5:  var(Camera) vector CamOffsetNear;
   6:   
   7:  /** max distance for camera */
   8:  var(Camera) vector CamOffsetFar;
   9:   
  10:  /** focus inner radius when in exploration mode */
  11:  var(PostProcess)   float fFocusRadiusExploration;
  12:   
  13:  /** movement speed */
  14:  var(Movement)   float Speed;
  15:   
  16:  /** jump force */
  17:  var(Movement)   float Jump;
  18:   
  19:  /** how much energy to drain at once */
  20:  var(Other)   float EnergyDrainAmount;
  21:   
  22:  /** distance to moveable object allowing its pickup */
  23:  var(Manipulate)   float PickupDistance;

Creating and archetype is really simple. Open your Content Browser, click on Actor classes tab, uncheck all checkboxes (as this is not placeable, nor actor) and find your properties object. Right click, create an archetype, specify your package and some cool name (like Properties ;) ) and there you go! From now on, all your global parameters are accessible via properties of this archetype (F4)




To have an access to properties archetype in unrealscript, just reference it in variables and default properties. After that you can access it as any default structure.


   1:  class BallPuzzlerCamera extends Camera;
   2:   
   3:  var const archetype BallPuzzlerProperties Properties; //declare variable
   4:   
   5:  ...
   6:   
   7:  //========================================================================
   8:  function ComputeCameraRotation(float DT)
   9:  {
  10:      local float partAngle;
  11:      
  12:      //use it!
  13:      partAngle = Properties.CamRotDelta * DT;
  14:   
  15:  ...
  16:   
  17:  defaultproperties
  18:  {
  19:      //define it as external from package
  20:      Properties=BallPuzzlerProperties'BallPuzzlerGame.Archetypes.Properties'
  21:  }

Monday, October 1, 2012

Cookbook: Triggering events, uscript -> kismet

Imagine you want to have a custom unrealscript actor (e.g. button). Obviously you want that button to introduce some interactivity to your scene/level. Let's say you want it to trigger some event for kismet (universal event that you want to be able to hook to any action available - play a matinee movie, toggle light, etc.)

What do we need?

1. create simple Seq_Event

All we need is a super simple event without any internal functionality. It's a good habit to organize it into some category (ObjCategory).


   1:  class SeqEvent_ButtonSet extends SequenceEvent;
   2:   
   3:  defaultproperties
   4:  {
   5:      ObjName="ButtonSet"       //kismet event name
   6:      ObjCategory="MyGame" //kismet event menu category
   7:      bPlayerOnly = false       //only pawn based actor can trigger?
   8:  }


2. trigger it from script

In our ButtonActor we need to trigger the given event somewhere. In this example it is triggered whenever touch event occurs (it'd be better to have some checks whether it's triggered by our pawn, some specific actor, etc.). To make our life easier, event is added to SupportedEvents in defaultproperties (this way it'll show in kismet right click menu when buttonActor is selected in scene).



   1:  class ButtonActor extends Actor
   2:      ClassGroup(MyGame) //group for actor classes menu (content browser)
   3:      placeable;
   4:   
   5:  ...
   6:   
   7:  //========================================================================
   8:  event Touch( Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal )
   9:  {
  10:      //trigger event with myself as instigator
  11:      TriggerEventClass(class'SeqEvent_ButtonSet', self);
  12:  }
  13:   
  14:  ...
  15:   
  16:  defaultproperties
  17:  {  
  18:      SupportedEvents.Add(class'SeqEvent_ButtonSet') //to see it in kismet (selected actor, add event using actor...)
  19:  }

3. connect it to some kismet action

Here we need to insert an instance of our button into scene and (with button selected) in kismet right click Add event using actor -> you'll see our new event in submenu, add it! After that, all that is left is to connect it to whatever action you want. Example image shows button that plays open the door animation and turns matching color lights connected to door and button off.