keywords:UE4, Create Component, Constructor, Runtime

Component

Constructor中 Create & Attach

MyActor.h:

UShapeComponent * CollisionMesh;

MyActor.cpp:

CollisionMesh = CreateDefaultSubobject<UBoxComponent>(TEXT("TestCollision"));
if(CollisionMesh)
{
    CollisionMesh->SetupAttachment(GetRootComponent());
}
Runtime中(非构造) Create & Attach

MyActor.cpp:

CollisionMesh = NewObject<UBoxComponent>(this);
if (CollisionMesh)
{
    CollisionMesh->RegisterComponent();
    CollisionMesh->AttachToComponent(GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform);
}

Actor

Constructor中 Create & Attach

很少情况下需要在构造函数执行Actor之间的相关Attach。

ConstructorHelpers::FObjectFinder<UMaterial> DecalMaterialAsset(TEXT("Material'/Game/TopDownCPP/Blueprints/M_Cursor_Decal.M_Cursor_Decal'"));
if (DecalMaterialAsset.Succeeded())
{
    DecalMaterialAsset.AttachToActor(MyActor, FAttachmentTransformRules::KeepRelativeTransform);
}
Runtime中Actor和Actor之间相互Attach
Actor1 = GetWorld()->SpawnActor<AMyActor>(AMyActor::StaticClass());
if(Actor1)
{
    Actor1->AttachToActor(Actor2, FAttachmentTransformRules::KeepRelativeTransform);
}

AttachToComponent()为引擎的仅次于UObject的子类ActorComponent的函数; AttachToActor为引擎的仅次于UObject的子类Actor的函数。

通过NewObject创建Component之后,执行Register的目的是为了触发OnComponentCreate等回调。不执行Create相关的Initial回调会导致后续的Attach失效。

注意:Actor::AttachToActor()和Actor::AttachTo()为4.12的新版API,旧版本的工程迁移至4.12后,编译提示警告:
AActor::AttachRootComponentToActor已废弃,需要使用AttachToActor替换

获取 ActorComponent 所属的 Actor
AActor* GetOwner() const;

GetOwner() 会沿着 ActorComponent 到 RootComponent 之间的从属链一直往上走,找到 RootComponent 并返回 RootComponent 所属的 Actor 对象。

Misc

自定义创建的Component如何在蓝图编辑器中被访问

UCLASS添加meta=(BlueprintSpawnableComponent)

UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class ROUGE_API UMyTestComponent : public UStaticMeshComponent
{
    GENERATED_BODY()
}