20201030 UE4 ActorComponent

Issue: Nested SceneComponent Does Not Show In Game

English

If you try to make a USceneComponent class, named A, creating, encapsulating and holding a reference to another USceneComponent B, you may find that B cannot show in the game.

As we all know, when we try to add a component to Actor, we must call AttachToComponent(RootComponent) and RegisterComponent(). That’s right.

But if you make a nested USceneComponent, remind that when you add this class to an Actor, you should not only call the outer USceneComponent‘s RegisterComponent, but also the inner’s.

BTW, do not try to call the inner USceneComponent‘s RegisterComponent() in the outer’s constructor, which may cause error.

Chinese

最近遇到个需求,需要把两个UStaticMeshComponent封装到一个SceneComponent中。

假设我们新建了USceneComponent类A,然后A持有两个UMeshComponentB和C。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class UA : public USceneComponent
{
public:

UPROPERTY()
UMeshComponent* B;

UPROPERTY()
UMeshComponent* C;

UA()
{
B = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("B"));
C = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("C"));
B->SetupAttachment(this);
C->SetupAttachment(this);
}
}

然后在某个Actor中,动态Add A(在)。

1
2
3
4
5
6
void AMyActor::AddShape()
{
_A = NewObject<UA>(This, TEXT("A"));
_A->AttachToComponent(RootComponent);
_A->RegisterComponent();
}

然后发现游戏运行之后一直没有显示出来两个Mesh。

此时我还不知道RegisterComponent()是干啥用的,总之就尝试先在A创建B和C之后先执行它们的RegisterComponent()

结果:

  • B和C能显示出来了
  • B和C没法跟着Actor的移动而移动
  • 重新开启Editor的时候会报错,说是RegisterComponent不能在构造函数线程里调用:

    if (ensure(MyOwnerWorld)) 这句话说明现在的World还没生成,或者没有Owner

于是又换了中写法,把B和C的RegisterComponent放到外头,在A被创建完毕之后再执行。

结果一切正常了。

结论

当出现SceneComponent再嵌套了其他SceneComponent的时候,如果要把它加到Actor上,这里面所有的SceneComponent都得执行一次RegisterComponent

概念区分

RegisterComponent

把控件注册到世界。不注册的话会没办法被tick和render,无法显示出来而且不会执行任何tick逻辑。

所以动态创建完控件之后一定要调用一下RegisterComponent()

神奇的是,如果Component是在Actor的构造函数中通过CreateDefaultSubobject()创建的,那么不执行RegisterComponent()也能够正常运行。

AttachToComponent, AttachTo, SetupAttachment

AttachToComponent是组件绑定,绑定到父类。要在非构造函数里面使用,如果在构造函数里面使用了,会发出一个警告,并且最终实际调用的是SetupAttachment

AttachToAttachToComponent是一样的结果,看源码可以发现它实际上调用的就是AttachToComponent,但是已经deprecated,如果调用,编译器会发出警告。

SetupAttachment在构造函数中被调用,用来先标记要attach到哪个parent。

Buy Me A Coffee / 捐一杯咖啡的钱
分享这篇文章~
0%
//