UDN
Search public documentation:

DevelopmentKitGemsIteratorKismetNodes
日本語訳
中国翻译
한국어

Interested in the Unreal Engine?
Visit the Unreal Technology site.

Looking for jobs and company info?
Check out the Epic games site.

Questions about support via UDN?
Contact the UDN Staff

UE3 Home > Unreal Development Kit Gems > Creating Iterator Kismet nodes
UE3 Home > Kismet Visual Scripting > Creating Iterator Kismet nodes

Creating Iterator Kismet nodes


Last tested against UDK Apr, 2011
PC and iOS compatible

Overview


Sometimes it's necessary to be able to find nearby pawns (players or monsters) or other kinds of actors that may not exist in the level during the level design phase. Or, sometimes you may want to attach special effects onto a certain kind of actor, but only if they are within a certain radius of something. This gem helps you to create new Kismet nodes which expose this functionality.

All Actors


The all actors node uses either an AllActors or a DynamicActors iterator to retrieve the desired actor filtered by class and or interface. The Kismet node works by first getting the reference to the WorldInfo by using the static function available in WorldInfo. The WorldInfo reference is needed because AllActors and DynamicActors require an Actor reference to work. Since WorldInfo is always available, and easy to find a reference to, it is chosen for this purpose. If a reference to WorldInfo is valid, the attached ObjectList kismet variable node is then found and type casted. If the level designer checked AlwaysClearObjectList, then the ObjectList's array is cleared before adding found actors to it. If the DynamicActorsOnly is checked, the the DynamicActors iterator is used to retrieve actor references. Otherwise the AllActors iterator is used to retrieve actor rferences. This was done primarily as a performance between the two iterators may make a difference.

  • ALERT! AllActors is slow, use sparingly.
  • ALERT! DynamicActors is faster than AllActors, consider other iterators if possible before using this.

Variables

  • ActorClass - Filter actors by class. Actors must be this class or a subclass.
  • InterfaceClass - Filter actors by interface implementation. Actors must implement this interface or subclassed interface.
  • AlwaysClearObjectList - Before filling the ObjectList with new actors, clear the ObjectList.
  • DynamicActorsOnly - Only search for actors within the non-static actor list.

Unrealscript

SeqAct_AllActors.uc
class SeqAct_AllActors extends SequenceAction;

var() class<Actor> ActorClass;
var() class<Interface> InterfaceClass;
var() bool AlwaysClearObjectList;
var() bool DynamicActorsOnly;

event Activated()
{
  local Actor Actor;
  local WorldInfo WorldInfo;
  local array<SequenceObject> ObjectList;
  local SeqVar_ObjectList SeqVar_ObjectList;
  
  if (ActorClass != None)
  {
    WorldInfo = class'WorldInfo'.static.GetWorldInfo();
    if (WorldInfo != None)
    {
      // Get the object list seq var
      GetLinkedObjects(ObjectList, class'SeqVar_ObjectList', false);

      if (ObjectList.Length > 0)
      {
        SeqVar_ObjectList = SeqVar_ObjectList(ObjectList[0]);

        if (SeqVar_ObjectList != None)
        {
          if (AlwaysClearObjectList)
          {
            SeqVar_ObjectList.ObjList.Length = 0;
          }

          if (DynamicActorsOnly)
          {
            ForEach WorldInfo.DynamicActors(ActorClass, Actor, InterfaceClass)
            {
              SeqVar_ObjectList.ObjList.AddItem(Actor);
            }
          }
          else
          {
            ForEach WorldInfo.AllActors(ActorClass, Actor, InterfaceClass)
            {
              SeqVar_ObjectList.ObjList.AddItem(Actor);
            }
          }
        }
      }
    }
  }

  ActivateOutputLink(0);
}

defaultproperties
{
  ObjName="All Actors"
  ObjCategory="Iterators"
  InputLinks(0)=(LinkDesc="In")
  OutputLinks(0)=(LinkDesc="Out")
  VariableLinks.Empty
  VariableLinks(0)=(ExpectedType=class'SeqVar_ObjectList',LinkDesc="Out Objects",bWriteable=true)
}

Using the All Actors Kismet node

In this example, the All Actors node is activated when the player touches a trigger on the ground. The All Actors node then finds all Note actors within the level. Finally, a random Note is picked from the ObjectList and an explosion is triggered at the Note's location.

KI_AllActorsTest.jpg

Based Actors


Based actors is useful when you want to find actors that are currently on top of another actor. For example, you may want to know how many actors are on top of a pressure platform. If there three pawns, then you decide that it is heavy enough to trigger another type of Kismet event. This particular example can already be achieved by using Touch triggers and so forth, but perhaps there is another way that this iterator Kismet node may be useful to you.

This iterator Kismet node does not need to find a reference to the WorldInfo because the iterator needs to be performed on a specific actor. Thus, the BaseActor variable is exposed to Kismet to allow the level designer to specify what actor to use. From there, the ObjectList is found and type casted. The level designer may check AlwaysClearObjectList to clear the object list before filling it with new actor references. Lastly the BasedActors iterator is called to find all of the actors that are currently based on BaseActor. The BasedActor iterator is fast.

Variables

  • ActorClass - Filter actors by class. Actors must be this class or a subclass.
  • AlwaysClearObjectList - Before filling the ObjectList with new actors, clear the ObjectList.

Unrealscript

SeqAct_BasedActors.uc
class SeqAct_BasedActors extends SequenceAction;

var() class<Actor> ActorClass;
var() bool AlwaysClearObjectList;
var Actor BaseActor;

event Activated()
{
  local Actor Actor;
  local array<SequenceObject> ObjectList;
  local SeqVar_ObjectList SeqVar_ObjectList;
  
  if (ActorClass != None && BaseActor != None)
  {
    // Get the object list seq var
    GetLinkedObjects(ObjectList, class'SeqVar_ObjectList', false);

    if (ObjectList.Length > 0)
    {
      SeqVar_ObjectList = SeqVar_ObjectList(ObjectList[0]);

      if (SeqVar_ObjectList != None)
      {
        if (AlwaysClearObjectList)
        {
          SeqVar_ObjectList.ObjList.Length = 0;
        }

        ForEach BaseActor.BasedActors(ActorClass, Actor)
        {
          SeqVar_ObjectList.ObjList.AddItem(Actor);
        }
      }
    }
  }

  ActivateOutputLink(0);
}

defaultproperties
{
  ObjName="Based Actors"
  ObjCategory="Iterators"
  InputLinks(0)=(LinkDesc="In")
  OutputLinks(0)=(LinkDesc="Out")
  VariableLinks.Empty
  VariableLinks(0)=(ExpectedType=class'SeqVar_ObjectList',LinkDesc="Out Objects",bWriteable=true)
  VariableLinks(1)=(ExpectedType=class'SeqVar_Object',LinkDesc="Base Actor",PropertyName=BaseActor)
}

Using the Based Actors Kismet node

In this example, a loop is set up when the level is loaded. At each loop interval, the Based Actors node finds all UTPawn actors that are currently based on the InterpActor in the level. It then finds the first valid object in the ObjectList and logs it onto the screen. The ObjectList is cleared immediately afterwards.

KI_BasedActorsTest.jpg

Child Actors


The Child Actors Kismet node returns all actor references that are currently owned by the OwningActor. Much like the Based Actors iterator Kismet node, the level designer is responsible for setting the OwningActor by using the exposed Kismet variable node. The code is very similar to the Based Actors iterator Kismet node, except that the ChildActors iterator is used instead.

  • ALERT! ChildActors is slow and should be avoided if possible

Variables

  • ActorClass - Filter actors by class. Actors must be this class or a subclass.
  • AlwaysClearObjectList - Before filling the ObjectList with new actors, clear the ObjectList.

Unrealscript

SeqAct_ChildActors.uc
class SeqAct_ChildActors extends SequenceAction;

var() class<Actor> ActorClass;
var() bool AlwaysClearObjectList;
var Actor OwningActor;

event Activated()
{
  local Actor Actor;
  local array<SequenceObject> ObjectList;
  local SeqVar_ObjectList SeqVar_ObjectList;
  
  if (ActorClass != None && OwningActor != None)
  {
    // Get the object list seq var
    GetLinkedObjects(ObjectList, class'SeqVar_ObjectList', false);

    if (ObjectList.Length > 0)
    {
      SeqVar_ObjectList = SeqVar_ObjectList(ObjectList[0]);

      if (SeqVar_ObjectList != None)
      {
        if (AlwaysClearObjectList)
        {
          SeqVar_ObjectList.ObjList.Length = 0;
        }

        ForEach OwningActor.ChildActors(ActorClass, Actor)
        {
          SeqVar_ObjectList.ObjList.AddItem(Actor);
        }
      }
    }
  }

  ActivateOutputLink(0);
}

defaultproperties
{
  ObjName="Child Actors"
  ObjCategory="Iterators"
  InputLinks(0)=(LinkDesc="In")
  OutputLinks(0)=(LinkDesc="Out")
  VariableLinks.Empty
  VariableLinks(0)=(ExpectedType=class'SeqVar_ObjectList',LinkDesc="Out Objects",bWriteable=true)
  VariableLinks(1)=(ExpectedType=class'SeqVar_Object',LinkDesc="Owning Actor",PropertyName=OwningActor)
}

Using the Child Actors Kismet node

In this example, a loop is set up upon level load. For each loop interval, the Child Actors node finds all UTPawn actors that are owned by the Player. A random object is then chosen from the ObjectList and logged on the screen.

KI_ChildActorsTest.jpg

Radial Actors


This iterator Kismet node finds actors within a radius. It also has options which allow level designers to filter out actors based on visibility, collision and if its overlapping. The visibility filter checks to see if the actor is hidden or not. The collision filter checks to see if the actor is collidable (bCollideActors is true) with other actors. The overlapping filter checks to see if the actor's collision components (bCollideActors is true) overlaps a sphere with the radii defined by Radius.

First a reference to the WorldInfo is acquired by using the static function within WorldInfo. If a valid WorldInfo is found, the ObjectList is then found and type casted so that it can be used. The location of the iterator is dependent on the following logic.

  • If ActorLocation has been used to reference an actor in the world, then use that Actor's location as the origin for the radius scan.
  • Otherwise use Location as the origin for the radius scan.

If AlwaysClearObjectList is checked, then the ObjectList is cleared before adding new items to it. From there the most appropriate iterator is used together with the various properties set by the level designer. The performance impact by this Kismet node depends on which type of iterator is used.

Variables

  • ActorClass - Filter actors by class. Actors must be this class or a subclass.
  • AlwaysClearObjectList - Before filling the ObjectList with new actors, clear the ObjectList.
  • IteratorType - Type of iterator to use.
    • Visible - Slow, avoid using this iterator type if possible.
    • Visible and Collidable - Fast as it uses the collision octree when a reasonably small radii is used.
      • Ignore Hidden - Ignores actors that are hidden.
      • Trace Extent - Extent to use when using traces to check if there is no world geometry between the origin and the actor's location.
      • Trace Actors - Check if you wish to perform a trace to check if there is no world geometry between the origin and the actor's location.
      • Interface Class - Set to something other than none if you wish to filter actors by interface implementation.
    • Collidable - Fast as it uses the collision octree when a reasonably small radii is used.
      • Use Overlap Check - Check to ensure that the actor is within the radii, instead of just checking if an actor's location is within the radii.
      • Interface Class - Set to something other than none if you wish to filter actors by interface implementation.
    • Overlapping - Slow, avoid using this iterator type if possible.
      • Ignore Hidden - Ignores actors that are hidden.

Unrealscript

SeqAct_RadialActors.uc
class SeqAct_RadialActors extends SequenceAction;

enum EIteratorType
{
  EIT_Visible<DisplayName="Visible">,
  EIT_VisibleColliding<DisplayName="Visible and Collidable">,
  EIT_Colliding<DisplayName="Collidable">,
  EIT_Overlapping<DisplayName="Overlapping">
};

var() class<Actor> ActorClass;
var() bool AlwaysClearObjectList;
var() EIteratorType IteratorType;

var() float Radius;
// Location will be overriden when using an attached actor
var() Vector Location;
var Actor ActorLocation;

var(VisibleCollidingActors) bool VCAIgnoreHidden<DisplayName="Ignore Hidden">;
var(VisibleCollidingActors) Vector VCAExtent<DisplayName="Trace Extent">;
var(VisibleCollidingActors) bool VCATraceActors<DisplayName="Trace Actors">;
var(VisibleCollidingActors) class<Interface> VCAInterfaceClass<DisplayName="Interface Class">;

var(CollidingActors) bool CAUseOverlapCheck<DisplayName="Use Overlap Check">;
var(CollidingActors) class<Interface> CAInterfaceClass<DisplayName="Interface Class">;

var(OverlappingActors) bool OAIgnoreHidden<DisplayName="Ignore Hidden">;

event Activated()
{
  local WorldInfo WorldInfo;
  local Actor Actor;
  local array<SequenceObject> ObjectList;
  local SeqVar_ObjectList SeqVar_ObjectList;
  local Vector IteratorLocation;

  if (ActorClass != None)
  {
    WorldInfo = class'WorldInfo'.static.GetWorldInfo();

    if (WorldInfo != None)
    {
      // Get the object list seq var
      GetLinkedObjects(ObjectList, class'SeqVar_ObjectList', false);

      if (ObjectList.Length > 0)
      {
        SeqVar_ObjectList = SeqVar_ObjectList(ObjectList[0]);

        if (SeqVar_ObjectList != None)
        {
          IteratorLocation = (ActorLocation != None) ? ActorLocation.Location : Location;

          if (AlwaysClearObjectList)
          {
            SeqVar_ObjectList.ObjList.Length = 0;
          }

          switch (IteratorType)
          {
          case EIT_Visible:
            ForEach WorldInfo.VisibleActors(ActorClass, Actor, Radius, IteratorLocation)
            {
              SeqVar_ObjectList.ObjList.AddItem(Actor);
            }
            break;

          case EIT_VisibleColliding:
            ForEach WorldInfo.VisibleCollidingActors(ActorClass, Actor, Radius, IteratorLocation, VCAIgnoreHidden, VCAExtent, VCATraceActors, VCAInterfaceClass)
            {
              SeqVar_ObjectList.ObjList.AddItem(Actor);
            }
            break;

          case EIT_Colliding:
            ForEach WorldInfo.CollidingActors(ActorClass, Actor, Radius, IteratorLocation, CAUseOverlapCheck, CAInterfaceClass)
            {
              SeqVar_ObjectList.ObjList.AddItem(Actor);
            }
            break;

          case EIT_Overlapping:
            ForEach WorldInfo.OverlappingActors(ActorClass, Actor, Radius, IteratorLocation, OAIgnoreHidden)
            {
              SeqVar_ObjectList.ObjList.AddItem(Actor);
            }
            break;

          default:
            break;
          }
        }
      }
    }
  }

  ActivateOutputLink(0);
}

defaultproperties
{
  ObjName="Radial Actors"
  ObjCategory="Iterators"
  InputLinks(0)=(LinkDesc="In")
  OutputLinks(0)=(LinkDesc="Out")
  VariableLinks.Empty
  VariableLinks(0)=(ExpectedType=class'SeqVar_ObjectList',LinkDesc="Out Objects",bWriteable=true)
  VariableLinks(1)=(ExpectedType=class'SeqVar_Float',LinkDesc="Radius",PropertyName=Radius)
  VariableLinks(2)=(ExpectedType=class'SeqVar_Object',LinkDesc="Actor Location",bHidden=true,PropertyName=ActorLocation)
  VariableLinks(3)=(ExpectedType=class'SeqVar_Vector',LinkDesc="Location",PropertyName=Location)
}

Using the Radial Actors Kismet node

In this example, the player's pawn is first found and stored when the player spawns. The Radial Actors note then searches for PathNodes that are within the radii, which is defined at 192.f, at the player's pawn's location. A random object is chosen from the ObjectList and a explosion is triggered at that object's location.

KI_RadiusActorsTest.jpg

Touching Actors


This iterator Kismet node returns all of the actors that are currently touching the BaseActor. Its code is very similar to the BasedActors iterator Kismet node, but using the TouchingActors iterator instead. This iterator is fast.

Variables

  • ActorClass - Filter actors by class. Actors must be this class or a subclass.
  • AlwaysClearObjectList - Before filling the ObjectList with new actors, clear the ObjectList.

Unrealscript

SeqAct_TouchingActors.uc
class SeqAct_TouchingActors extends SequenceAction;

var() class<Actor> ActorClass;
var() bool AlwaysClearObjectList;
var Actor BaseActor;

event Activated()
{
  local Actor Actor;
  local array<SequenceObject> ObjectList;
  local SeqVar_ObjectList SeqVar_ObjectList;
  
  if (ActorClass != None && BaseActor != None)
  {
    // Get the object list seq var
    GetLinkedObjects(ObjectList, class'SeqVar_ObjectList', false);

    if (ObjectList.Length > 0)
    {
      SeqVar_ObjectList = SeqVar_ObjectList(ObjectList[0]);

      if (SeqVar_ObjectList != None)
      {
        if (AlwaysClearObjectList)
        {
          SeqVar_ObjectList.ObjList.Length = 0;
        }

        ForEach BaseActor.TouchingActors(ActorClass, Actor)
        {
          SeqVar_ObjectList.ObjList.AddItem(Actor);
        }
      }
    }
  }

  ActivateOutputLink(0);
}

defaultproperties
{
  ObjName="Touching Actors"
  ObjCategory="Iterators"
  InputLinks(0)=(LinkDesc="In")
  OutputLinks(0)=(LinkDesc="Out")
  VariableLinks.Empty
  VariableLinks(0)=(ExpectedType=class'SeqVar_ObjectList',LinkDesc="Out Objects",bWriteable=true)
  VariableLinks(1)=(ExpectedType=class'SeqVar_Object',LinkDesc="Base Actor",PropertyName=BaseActor)
}

Using the Touching Actors Kismet node

In this example, a loop is set up when the level is loaded. For each loop interval, the Touching Actors node looks for all UTProj_LinkPlasma actors that are current touching Trigger_0. A random object is then chosen from the ObjectList and logged on the screen. The ObjectList is cleared immediately afterwards.

KI_TouchingActorsTest.jpg

Trace Actors


This iterator Kismet node performs a trace between TraceStart and TraceEnd. TraceExtent defines the width and height of the trace (non-zero extent trace) if it is required. This iterator Kismet node can be useful when you want to find actors in a straight line, such as a laser beam.

First a reference to the WorldInfo is found by using the static function available within WorldInfo. From there, the ObjectList is found and type casted. If AlwaysClearObjectList is checked, the the ObjectList is cleared. Finally, a TraceActors iterator is performed using the TraceStart, TraceEnd and TraceExtent inputs. HitLocation and HitNormal information gathered by the iterator is discarded. All actors within the trace points are then inserted in to the ObjectList. Reasonably fast like any trace.

Variables

  • ActorClass - Filter actors by class. Actors must be this class or a subclass.
  • AlwaysClearObjectList - Before filling the ObjectList with new actors, clear the ObjectList.
  • TraceStart - Where to start the trace.
  • TraceEnd - Where to end the trace.
  • TraceExtent - Thickness of the trace. Can be zero to use zero-extent traces.

Unrealscript

SeqAct_TraceActors.uc
class SeqAct_TraceActors extends SequenceAction;

var() class<Actor> ActorClass;
var() bool AlwaysClearObjectList;
var() Vector TraceStart;
var() Vector TraceEnd;
var() Vector TraceExtent;

event Activated()
{
  local WorldInfo WorldInfo;
  local Actor Actor;
  local array<SequenceObject> ObjectList;
  local SeqVar_ObjectList SeqVar_ObjectList;
  local Vector HitLocation, HitNormal;

  if (ActorClass != None)
  {
    WorldInfo = class'WorldInfo'.static.GetWorldInfo();

    if (WorldInfo != None)
    {
      // Get the object list seq var
      GetLinkedObjects(ObjectList, class'SeqVar_ObjectList', false);

      if (ObjectList.Length > 0)
      {
        SeqVar_ObjectList = SeqVar_ObjectList(ObjectList[0]);

        if (SeqVar_ObjectList != None)
        {
          if (AlwaysClearObjectList)
          {
            SeqVar_ObjectList.ObjList.Length = 0;
          }

          ForEach WorldInfo.TraceActors(ActorClass, Actor, HitLocation, HitNormal, TraceEnd, TraceStart, TraceExtent)
          {
            SeqVar_ObjectList.ObjList.AddItem(Actor);
          }
        }
      }
    }
  }

  ActivateOutputLink(0);
}

defaultproperties
{
  ObjName="Trace Actors"
  ObjCategory="Iterators"
  InputLinks(0)=(LinkDesc="In")
  OutputLinks(0)=(LinkDesc="Out")
  VariableLinks.Empty
  VariableLinks(0)=(ExpectedType=class'SeqVar_ObjectList',LinkDesc="Out Objects",bWriteable=true)
  VariableLinks(1)=(ExpectedType=class'SeqVar_Vector',LinkDesc="Trace Start",PropertyName=TraceStart)
  VariableLinks(2)=(ExpectedType=class'SeqVar_Vector',LinkDesc="Trace End",PropertyName=TraceEnd)
  VariableLinks(3)=(ExpectedType=class'SeqVar_Vector',LinkDesc="Trace Extent",PropertyName=TraceExtent)
}

Using the Trace Actors Kismet node

In this example, the location of Note_0 and Note_1 is first found. A looping setup is then created when these two variables have been set. For each loop interval, the Trace Actors performs a trace between Note_0 and Note_1; looking for any UTPawns within the trace. A random object is then chosen from the ObjectList. A log is written on the screen and an alarm sound is played back. The ObjectList is immediately cleared after that.

KI_TraceActorsTest.jpg

Downloads


  • Download the source code and maps used in this gem. (KismetIterators.zip)