Thursday, October 4, 2012

Cookbook: Moving actors in UDK using physics

Imagine you have your ball actor and you want to control it with input keys. You want it to roll in some direction if the key is pressed. Very easy way to achieve this on rigid bodies is by utilizing physics.

You only need to have your actor PrimitiveComponent in PHYS_RigidBody state:


   1:  //========================================================================
   2:  defaultProperties
   3:  {   
   4:      Begin Object Name=StaticMeshComponent0
   5:          StaticMesh=StaticMesh'BallPuzzlerGame.Actors.PlayerBall'
   6:          bNotifyRigidBodyCollision=false
   7:          CastShadow=true
   8:          BlockRigidBody=true
   9:          bCastDynamicShadow=true
  10:          HiddenGame=false
  11:          LightEnvironment=MyLightEnvironment
  12:      End Object
  13:      Components.Add(StaticMeshComponent0)
  14:      
  15:      Physics=PHYS_RigidBody //set physics!
  16:  }

Then there are multiple possibilities how to move it using impulses/force, etc. (check PrimitiveComponent documentation for other possibilities):


   1:  native final function AddImpulse(vector Impulse, ...);
   2:   
   3:  native final function AddForce(vector Force, ...);

And of course, teleporting (useful for resetting to some initial position):


   1:  native final function SetRBPosition(vector NewPos, ...);

Let's see it in some example. I'm moving my ball-like actor using AddImpulse, applying custom gravity using AddForce and can interact (pick up, move, put down, throw) using SetRBPosition (overriding original one, while being held) and AddImpulse when throwing:

   1:  // Use the player's input to move character
   2:  simulated function AddInputForce(float DeltaTime, vector MovementDir)
   3:  {
   4:      StaticMeshComponent.AddImpulse(MovementDir * DeltaTime * Properties.Speed);
   5:  }
   6:   
   7:  //apply gravity in custom direction
   8:  simulated function GravityForce( float DeltaTime )
   9:  {
  10:       StaticMeshComponent.AddForce(GravityVector*Properties.Gravity);
  11:  }
  12:   
  13:  //handle being locked
  14:  simulated event Tick(Float DT)
  15:  {
  16:      //we are locked, follow owner, override default behaviour
  17:      if (lockInstigator != none)
  18:      {
  19:          StaticMeshComponent.SetRBPosition(lockInstigator.Location + lockTranslation);
  20:      }
  21:      else
  22:      {
  23:          super.Tick(DT); //basic behavior
  24:      }
  25:  }

Here is a video showing all this in motion:


Wednesday, October 3, 2012

Cookbook: UDK set of objects instead of a Pawn

Normally, UDK is mainly a framework for first/third person shooter games. Many things are hardcoded, like necessity to have a Pawn as you main character (or references to UT3 in DefaultEngine.ini). For smaller (indie) projects that is many times not desired. What if you want to be able to control a simple KActor or some set of objects (like chess pieces)? That is not a problem!

insert instances of desired objects into scene (I'm controlling one actor):



collect references to your objects in some early phase:


   1:  var MyActorClass MyActor
   2:   
   3:  simulated event PostBeginPlay()
   4:  {
   5:      super.PostBeginPlay(); //call parent
   6:      
   7:      //iterate through all actors of given class and store them!
   8:      foreach WorldInfo.DynamicActors(class'MyActorClass', MyActor)
   9:      {
  10:          //some additional init?
  11:          Init();
  12:          break; //if interested only in first one
  13:      }
  14:  }

override Pawn dependent behavior in your custom classes to work with your actors (example from custom 3rd person camera):


   1:  class MyCamera extends Camera;
   2:   
   3:  //override, use your actor as the point of interest for camera
   4:  function UpdateViewTarget(out TViewTarget OutVT, float DeltaTime)
   5:  {
   6:      super.UpdateViewTarget(OutVT,DeltaTime);
   7:   
   8:      //add some offset to the target's for 3rd person camera
   9:      OutVT.POV.Location = MyActor.Location + Properties.CamOffset;
  10:   
  11:      // Make the camera point towards the target's location
  12:      OutVT.POV.Rotation = Rotator(MyActor.Location - OutVT.POV.Location);
  13:  }