类型转换 & Actor 附加

在上一篇文章中,我们遇到一个小问题:门无法下降到底。在这篇文章中,我们着手解决这个问题。

我们解决的方式是,将雕塑 Actor 附加到 Box 组件下,并关闭雕塑 Actor 的物理模拟。这样不仅能一直触发重叠,还能保证雕塑能随着门一起移动,而且不会因为物理模拟被挤出。

具体的代码实现如清单 1 所示,其中调用了 AttachToComponent()SetSimulatePhysics() 这两个函数,来实现上述功能。

代码清单 1 代码实现
  1. // Called every frame
  2. void UTriggerComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
  3. {
  4.     Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
  5.  
  6.     AActor* Actor = GetAcceptableActor();
  7.     if (Actor != NULL)
  8.     {
  9.         UE_LOG(LogTemp, Display, TEXT("Unlocking"));
  10.         UPrimitiveComponent* Component = Cast<UPrimitiveComponent>(Actor->GetRootComponent());
  11.         if (Mover != NULL && Component != NULL)
  12.         {
  13.             Component->SetSimulatePhysics(false);
  14.             Actor->AttachToComponent(this, FAttachmentTransformRules::KeepWorldTransform);
  15.             Mover->SetShouldMove(true);
  16.         }
  17.     }
  18.     else
  19.     {
  20.         if (Mover != NULL)
  21.             Mover->SetShouldMove(false);
  22.     }
  23. }

AttachToComponent() 函数用于将一个 Actor 附加到一个组件上。其函数原型为:

  • bool AActor::AttachToComponent(USceneComponent* Parent,
  •     const FAttachmentTransformRules& AttachmentRules,
  •     FName SocketName);

Parent 参数指定希望附加的组件。此处指定为 this 指针,即附加到当前的 Box 组件下。

AttachmentRules 参数指定附加时,Actor 位置、旋转、缩放的规则。此处指定为 KeepWorldTransform,它表示附加时保持世界位置、旋转、缩放不变。即引擎会自动调整 Actor 的相对位置,使其附加上去后,Actor 在世界空间中看起来是“没动”的。

SetSimulatePhysics() 函数用于控制组件开启或关闭物理模拟。注意这个函数是 UPrimitiveComponent 类的成员函数。

  • void UPrimitiveComponent::SetSimulatePhysics(bool bSimulate);

我们如何获取 Actor 下的 UPrimitiveComponent 指针呢?我们可以先通过 GetRootComponent() 函数,获取 Actor 的根组件指针,它是 USceneComponent 类型。然后再将其向下转化为 UPrimitiveComponent 类型。

USceneComponent 是 Unreal Engine 里所有带有位置信息的组件基类。UPrimitiveComponentUSceneComponent 的子类,进一步提供了渲染能力和碰撞检测能力。更进一步的继承关系如下:

  • UObject
  •  └── UActorComponent
  •       └── USceneComponent         // 有空间位置信息
  •            └── UPrimitiveComponent // 有形体和碰撞
  •                 └── UStaticMeshComponent(静态模型)
  •                 └── USphereComponent(碰撞球)
  •                 └── USkeletalMeshComponent(骨骼动画)

因为 USceneComponentUPrimitiveComponent 是向下转换,必须确保安全,所以必须使用 Unreal Engine 里的 Cast 函数。

转换原理暂不深究。单从效果上来看,可以类比 C++ 的 dynamic_cast。

运行程序。如下方视频所示,现在门可以下降到底了,可以走向下一片区域。