类型转换 & Actor 附加
在上一篇文章中,我们遇到一个小问题:门无法下降到底。在这篇文章中,我们着手解决这个问题。
我们解决的方式是,将雕塑 Actor 附加到 Box 组件下,并关闭雕塑 Actor 的物理模拟。这样不仅能一直触发重叠,还能保证雕塑能随着门一起移动,而且不会因为物理模拟被挤出。
具体的代码实现如清单 1 所示,其中调用了 AttachToComponent() 和 SetSimulatePhysics() 这两个函数,来实现上述功能。
- // Called every frame
- void UTriggerComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
- {
- Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
- AActor* Actor = GetAcceptableActor();
- if (Actor != NULL)
- {
- UE_LOG(LogTemp, Display, TEXT("Unlocking"));
- UPrimitiveComponent* Component = Cast<UPrimitiveComponent>(Actor->GetRootComponent());
- if (Mover != NULL && Component != NULL)
- {
- Component->SetSimulatePhysics(false);
- Actor->AttachToComponent(this, FAttachmentTransformRules::KeepWorldTransform);
- Mover->SetShouldMove(true);
- }
- }
- else
- {
- if (Mover != NULL)
- Mover->SetShouldMove(false);
- }
- }
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 里所有带有位置信息的组件基类。UPrimitiveComponent 是 USceneComponent 的子类,进一步提供了渲染能力和碰撞检测能力。更进一步的继承关系如下:
- UObject
- └── UActorComponent
- └── USceneComponent // 有空间位置信息
- └── UPrimitiveComponent // 有形体和碰撞
- └── UStaticMeshComponent(静态模型)
- └── USphereComponent(碰撞球)
- └── USkeletalMeshComponent(骨骼动画)
因为 USceneComponent 转 UPrimitiveComponent 是向下转换,必须确保安全,所以必须使用 Unreal Engine 里的 Cast 函数。
转换原理暂不深究。单从效果上来看,可以类比 C++ 的 dynamic_cast。
运行程序。如下方视频所示,现在门可以下降到底了,可以走向下一片区域。