UDN
Search public documentation:

DevelopmentKitGemsIteratorKismetNodesCH
English Translation
日本語訳
한국어

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 主页 > 虚幻开发工具包精华文章 > 创建迭代器 Kismet 节点
UE3 主页 > Kismet 可视化脚本 > 创建迭代器 Kismet 节点

创建迭代器 Kismet 节点


最后一次测试是在2011年4月份的UDK版本上进行的。
可以与 PC 和 iOS 兼容

概述


有时必需可以找到附近的 pawn(玩家或者怪物)或者其他种类的 actor,他们可能在关卡设计阶段过程中在关卡中不存在。或者,有时您可能需要将特效附加在某种 actor 上,但是只有在它们在某种东西的特定半径范围内时才可以附加。这篇精华文章将会帮助您创建可以展示该功能的新 Kismet 节点。

All Actor(所有 Actor)


所有 actor 节点使用 AllActors 或 DynamicActors 迭代器获取所需的由类和/或接口过滤的 actor。Kismet 节点首先通过使用在 WorldInfo 中提供的静态函数获取到 WorldInfo 的引用进行工作。需要 WorldInfo 引用是因为 AllActor 和 DynamicActor 需要 Actor 引用才能工作。由于 WorldInfo 始终可用,并且对它的引用容易查找,出于这个目的才选择它。如果对 WorldInfo 的引用是有效的,那么接下来就会找到这个附加的 ObjectList kismet 变量并进行类型转换。如果关卡设计师勾选了 AlwaysClearObjectList ,那么在向 ObjectList 的数列中添加找到的 actor 之前会数显清理这个数列。如果勾选了 DynamicActorsOnly ,那么使用 DynamicActors 迭代器获取 actor 引用。否则使用 AllActor 迭代器获取 actor 引用。主要是在性能介于两个可能不同的迭代器之间的情况下进行这项操作。

  • ALERT! AllActors 比较慢,请小心使用。
  • ALERT! DynamicActors 比 AllActor 速度快,如果可以请在使用它之前考虑使用其他迭代器。

Variables(变量)

  • ActorClass - 根据类过滤 actor。Actor 必须是这个类或子类。
  • InterfaceClass - 根据接口实现过滤 actor。Actor 必须实现这个接口或继承接口。
  • AlwaysClearObjectList - 在使用新 actor 填充 ObjectList 之前,清空 ObjectList。
  • DynamicActorsOnly - 只搜索非静态 actor 列表中的 actor。

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)
    {
      // 获取对象列表 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)
}

使用 All Actor Kismet 节点

在这个示例中,会在玩家解除到地面上的触发器时激活 All Actor 节点。接下来 All Actor 节点会找到关卡中的所有 Note actor。最后,从 ObjectList 中随机选取一个 Note,然后在这个 Note 的位置触发爆炸事件。

KI_AllActorsTest.jpg

基础的 Actor


基础的 actor 可以在您想要查找当前位于另一个 actor 顶部的 actor 时使用。例如,您可能想要了解有多少 actor 位于压力平台的顶部。如果有三个 pawn,那么您可以确定触发另一个类型的 Kismet 事件是非常困难的。到目前为止,这个特别的示例已经可以通过使用 Touch(触摸)触发器实现,但是这个迭代器 Kismet 节点对于您可能会有其他用处。

这个迭代器 Kismet 节点不需要找到对 WorldInfo 的引用,因为迭代器需要在特定的 actor 上执行。因此,向 Kismet 显示 BaseActor 变量,使关卡设计师可以指定要使用的 actor。在这里,找到了 ObjectList 以及转换的类型。关卡设计师可以在填充新的 actor 引用之前勾选 AlwaysClearObjectList 清除对象列表。最后会调用 BasedActors 迭代器查找当前基于 BaseActor 的所有 actor。BasedActor 迭代器很快。

Variables(变量)

  • ActorClass - 根据类过滤 actor。Actor 必须是这个类或子类。
  • AlwaysClearObjectList - 在使用新 actor 填充 ObjectList 之前,清空 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)
  {
    // 获取对象列表 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)
}

使用 Based Actor Kismet 节点

在这个示例中,加载关卡的时候会对循环进行设置。在每个循环间隔的时候,Based Actor 节点会找到关卡中当前基于 InterpActor 的所有 UTPawn actor。然后在 ObjectList 中查找第一个有效的对象并将其记录到屏幕上。之后立即清除 ObjectList。

KI_BasedActorsTest.jpg

Child Actor(子代 actor)


Child Actor Kismet 节点会返回当前归属于 OwningActor 的所有 actor 引用。与 Based Actors 迭代器 Kismet 节点非常相像,关卡设计师负责使用显示的 Kismet 变量节点设置 OwningActor 。代码与 Based Actor 迭代器 Kismet 节点非常接近,只是使用的是 ChildActor 迭代器。

  • ALERT! ChildActors 很慢,而且如果可以应该避免这种情况

Variables(变量)

  • ActorClass - 根据类过滤 actor。Actor 必须是这个类或子类。
  • AlwaysClearObjectList - 在使用新 actor 填充 ObjectList 之前,清空 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)
  {
    // 获取对象列表 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)
}

使用 Child Actor Kismet 节点

在这个示例中,加载关卡的时候会对循环进行设置。对于每个循环间隔,Child Actor 节点都会找到归属于这个 Player 的所有 UTPawn actor。然后从这个 ObjectList 中选取随机对象并将其记录到屏幕上。

KI_ChildActorsTest.jpg

Radial Actor(径向 Actor)


这个迭代器 Kismet 节点会查找径向中的 actor。它还有可以使关卡根据可视性和碰撞(如果它重叠)过滤 actor 的选项。可视性过滤可以检查 actor 是否被隐藏。碰撞过滤可以检查这个 actor 是否会与其他 actor 碰撞(bCollideActors 为 true)。重叠的过滤可以检查这个 actor 的碰撞组件(bCollideActors 为 true)是否与半径由 Radius(径向) 定义的球体互相重叠。

首先,通过使用 WorldInfo 中的静态函数获取一个对 WorldInfo 的引用。如果找到了一个有效的 WorldInfo,那么会找到这个 ObjectList 以及转换的类型,这样就可以使用它了。迭代器的位置根据下面的逻辑规则确定。

  • 如果已经使用 ActorLocation 引用世界中的 actor,那么将这个 Actor 的位置作为径向扫描的原点。
  • 否则将 Location(位置) 作为径向扫描的原点。

如果勾选了 AlwaysClearObjectList ,那么在向 ObjectList 中添加新内容之前将其全清空。在这里,将最合适的迭代器与关卡设计师设置的各种属性结合在一起使用。这个 Kismet 节点对性能产生的影响由使用的迭代器类型决定。

Variables(变量)

  • ActorClass - 根据类过滤 actor。Actor 必须是这个类或子类。
  • AlwaysClearObjectList - 在使用新 actor 填充 ObjectList 之前,清空 ObjectList。
  • IteratorType - 要使用的迭代器的类型。
    • Visible - 慢,如果可以避免使用这个迭代器类型。
    • Visible and Collidable - 快,因为它在使用非常小的半径时会使用碰撞 octree。
      • Ignore Hidden - 忽略被隐藏的 actor。
      • Trace Extent - 在使用轨迹检查在原点和 actor 的位置之间是否没有世界几何体的时候要使用的范围。
      • Trace Actors - 检查在您希望执行一个追踪的情况下原点和这个 actor 的位置之间是否没有世界几何体。
      • Interface Class - 在您希望通过接口实现过滤 actor 的情况下设置不为无的内容。
    • Collidable - 快,因为它在使用非常小的半径时会使用碰撞 octree。
      • Use Overlap Check - 检查确保这个 actor 在半径范围内,而不只是检查 actor 的位置是否在半径范围内。
      • Interface Class - 在您希望通过接口实现过滤 actor 的情况下设置不为无的内容。
    • Overlapping - 慢,如果可以避免使用这个迭代器类型。
      • Ignore Hidden - 忽略被隐藏的 actor。

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;
// 在使用一个附加的 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)
    {
      // 获取对象列表 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)
}

使用 Radial Actor Kismet 节点

在这个示例中,首先会发现玩家的 pawn,然后在玩家生成的时候对其进行存储。接下来 Radial Actor(径向 Actor)节点会在玩家 pawn 的位置搜索在这个半径范围内的 PathNode,将其定义为 192.f。从 ObjectList 中选取一个随机的对象,然后会在该对象的位置触发爆炸现象。

KI_RadiusActorsTest.jpg

Touching Actor(触摸 Actor)


这个迭代器 Kismet 节点会返回当前触摸到 BaseActor 的所有 actor。它的代码与 BasedActors 迭代器 Kismet 节点非常相近,但是使用的是 TouchingActor 迭代器。这个迭代器很快。

Variables(变量)

  • ActorClass - 根据类过滤 actor。Actor 必须是这个类或子类。
  • AlwaysClearObjectList - 在使用新 actor 填充 ObjectList 之前,清空 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)
  {
    // 获取对象列表 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)
}

使用 Touching Actor Kismet 节点

在这个示例中,加载关卡的时候会对循环进行设置。对于每个虚幻间隔,Touching Actor 节点会查找当前触摸到 Trigger_0 的所有 UTProj_LinkPlasma actor。从 ObjectList 中选取一个随机的对象并将其记录到屏幕上。之后立即清除 ObjectList。

KI_TouchingActorsTest.jpg

Trace Actor(跟踪 Actor)


这个迭代器 Kismet 节点会在 TraceStartTraceEnd 之间进行跟踪。如果需要, TraceExtent 会定义跟踪的宽度和高度(非零范围跟踪)。这个迭代器 Kismet 节点在您想要在一个直线中找到 actor 时非常有用,例如,激光光束。

首先,通过使用 WorldInfo 中提供的静态函数找到一个对 WorldInfo 的引用。在这里,找到了 ObjectList 以及转换的类型。如果勾选了 AlwaysClearObjectList ,那么会清空 ObjectList。最后,使用 TraceStartTraceEndTraceExtent 输入执行 TraceActor 迭代器。删除通过这个迭代器收集的 HitLocationHitNormal 信息。然后将跟踪点范围内的所有 actor 插入到这个 ObjectList 中。与任何跟踪一样非常快。

Variables(变量)

  • ActorClass - 根据类过滤 actor。Actor 必须是这个类或子类。
  • AlwaysClearObjectList - 在使用新 actor 填充 ObjectList 之前,清空 ObjectList。
  • TraceStart - 要开始跟踪的地方。
  • TraceEnd - 要结束跟踪的地方。
  • TraceExtent - 跟踪的范围。可以使用零范围跟踪。

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)
    {
      // 获取对象列表 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)
}

使用 Trace Actor Kismet 节点

在这个示例中,首先找到了 Note_0 和 Note_1 的位置。然后在设置好这两个变量后创建循环设置。对于每个循环间隔,Trace Actor 都会在 Note_0 和 Note_1 之间进行跟踪;在这个轨迹内部查找任何 UTPawn。然后从这个 ObjectList 中随机选取一个对象。在屏幕上写入日志记录,然后播放警报声。在这之后立即清空 ObjectList。

KI_TraceActorsTest.jpg

下载


  • 下载在这篇精华文章中使用的源代码和地图。(KismetIterators.zip)