UE4 Actor和Component
在UE4游戏场景中看到的所有对象皆是Actor
,而Actor
复杂的功能是由许多不同的Component
共同实现的。UActorComponent
提供最一般的功能,USceneComponent
提供三维的空间变换以及嵌套功能,UPrimitiveComponent
提供了可视化的功能。因此可以根据需要继承不同的组件类来实现自定义的组件类。
示例
UObject 的生成
Actor
和Component
都是UObject,有两种生成方式。
构造函数中 CreateDefaultSubobject
UHexTile* newTile = CreateDefaultSubobject<UHexTile>(TEXT("HexTileName"));
构造函数外 NewObject
static int32 TileCounter = 0;
FString TileName = FString::Printf(TEXT("HexTile_%d"), TileCounter++);
UHexTile* NewTile = NewObject<UHexTile>(this, UHexTile::StaticClass(), *TileName);
Actor & ActorComponent
在Actor子类构造函数中添加自定义的ActorComponent子类对象。
ArcGISRendererComponent = CreateDefaultSubobject<UArcGISRendererComponent>(TEXT("ArcGISRendererComponent"));
AddOwnedComponent(ArcGISRendererComponent);
Actor & StaticMeshComponent
在Actor子类构造函数中添加StaticMeshComponent对象。
VisualMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
VisualMesh->SetupAttachment(RootComponent);
static ConstructorHelpers::FObjectFinder<UStaticMesh> CubeAsset(TEXT("StaticMesh'/Game/Mesh/Cube.Cube'"));
if (CubeAsset.Succeeded()) {
VisualMesh->SetStaticMesh(CubeAsset.Object);
VisualMesh->SetRelativeLocation(FVector(0.0f,0.0f,0.0f));
}
创建Actor(SpawnActor)
// Create our sample pawn
ASampleDefaultPawn* arcGISPawn = GetWorld()->SpawnActor<ASampleDefaultPawn>();
// ASSIGN RENDERERVIEW TO THE CURRENT MAIN CAMERA COMPONENT
auto cameraComponent = arcGISPawn->FindComponentByClass<UArcGISCameraComponent>();
cameraComponent->RendererView = rendererView;
arcGISPawn->SetActorLocationAndRotation(Convert::ToFVector(rendererView->GetCameraLocalPosition()),
Convert::ToFQuat(rendererView->GetCameraLocalRotation()));
向Actor对象增加功能组件
构造函数外添加组件。
// Add reposition components to the directional and sky lights
auto directionalLightActor = UGameplayStatics::GetActorOfClass(GetWorld(), ADirectionalLight::StaticClass());
auto skyLightActor = UGameplayStatics::GetActorOfClass(GetWorld(), ASkyLight::StaticClass());
if (directionalLightActor)
{
auto directionalLightReposition = NewObject<UArcGISDirectionalLightRepositionComponent>(
directionalLightActor, UArcGISDirectionalLightRepositionComponent::StaticClass(), NAME_None, RF_Transient);
directionalLightReposition->RendererView = rendererView;
directionalLightReposition->RegisterComponent();
}
if (skyLightActor)
{
auto lightReposition =
NewObject<UArcGISSkyLightRepositionComponent>(skyLightActor, UArcGISSkyLightRepositionComponent::StaticClass(), NAME_None, RF_Transient);
lightReposition->RendererView = rendererView;
lightReposition->RegisterComponent();
}
组件中反查父Actor
auto owner = CastChecked<ASkyLight>(GetOwner());
owner->SetActorLocation(location);
auto skyLightComponent = StaticCast<USkyLightComponent*>(owner->GetLightComponent());
skyLightComponent->RecaptureSky();
遍历Actor,查找组件
static auto actorClasses =std::vector<TSubclassOf<UActorComponent>>{UArcGISLocationComponent::StaticClass(), UArcGISCameraComponent::StaticClass(), UArcGISDirectionalLightRepositionComponent::StaticClass()};
// Matrix transform from the old coordinate system to the new one
auto mTransform = CoordinateSystem.Inverse() * coordinateSystem;
for (TActorIterator<AActor> it(GetWorld()); it; ++it)
{
auto* actor = *it;
for (const auto& actorClass : actorClasses)
{
auto component = actor->GetComponentByClass(actorClass);
if (component)
{
Vector3d newLocation;
Quaternion newRotation;
if (actorClass == actorClasses[0])
{
const auto coord = Cast<UArcGISLocationComponent>(component);
const auto latLon = LatLon(coord->Latitude, coord->Longitude, coord->Altitude);
const auto rotator = Rotator(coord->Heading, coord->Pitch, coord->Roll);
if (RendererView->GetSceneType() == SceneType::Global)
{
Vector3d cartesianPosition = Coordinates::WGS84SphericalToECEF(latLon);
newLocation = coordinateSystem.TransformPosition(cartesianPosition);
newRotation = coordinateSystem.ToQuaternion() * Coordinates::GetENUCoordinateSystemGlobal(cartesianPosition);
}
else
{
Vector3d cartesianPosition = Coordinates::WGS84SphericalToCartesianPlanar(latLon);
newLocation = coordinateSystem.TransformPosition(cartesianPosition);
newRotation = coordinateSystem.ToQuaternion() * Coordinates::GetENUCoordinateSystemLocal(cartesianPosition);
}
}
else
{
newLocation = mTransform.TransformPosition(Convert::FromFVector(actor->GetActorLocation()));
newRotation = mTransform.ToQuaternion() * Convert::FromFQuat(actor->GetActorRotation().Quaternion());
}
actor->SetActorLocationAndRotation(Convert::ToFVector(newLocation), Convert::ToFQuat(newRotation).Rotator(), false, nullptr,
ETeleportType::ResetPhysics);
break;
}
}
}